author | wenzelm |
Fri, 03 May 2024 00:24:57 +0200 | |
changeset 80171 | 9e88c17a723e |
parent 76987 | 4c275405faae |
permissions | -rw-r--r-- |
72991 | 1 |
(*<*)theory Axioms imports Overloading "../Setup" begin(*>*) |
31678 | 2 |
|
67406 | 3 |
subsection \<open>Axioms\<close> |
31678 | 4 |
|
67406 | 5 |
text \<open>Attaching axioms to our classes lets us reason on the level of |
31678 | 6 |
classes. The results will be applicable to all types in a class, just |
7 |
as in axiomatic mathematics. |
|
8 |
||
9 |
\begin{warn} |
|
10 |
Proofs in this section use structured \emph{Isar} proofs, which are not |
|
76987 | 11 |
covered in this tutorial; but see \<^cite>\<open>"Nipkow-TYPES02"\<close>.% |
67406 | 12 |
\end{warn}\<close> |
31678 | 13 |
|
67406 | 14 |
subsubsection \<open>Semigroups\<close> |
31678 | 15 |
|
69597 | 16 |
text\<open>We specify \emph{semigroups} as subclass of \<^class>\<open>plus\<close>:\<close> |
31678 | 17 |
|
18 |
class semigroup = plus + |
|
19 |
assumes assoc: "(x \<oplus> y) \<oplus> z = x \<oplus> (y \<oplus> z)" |
|
20 |
||
67406 | 21 |
text \<open>\noindent This @{command class} specification requires that |
69597 | 22 |
all instances of \<^class>\<open>semigroup\<close> obey @{fact "assoc:"}~@{prop |
61076 | 23 |
[source] "\<And>x y z :: 'a::semigroup. (x \<oplus> y) \<oplus> z = x \<oplus> (y \<oplus> z)"}. |
10328 | 24 |
|
31678 | 25 |
We can use this class axiom to derive further abstract theorems |
69597 | 26 |
relative to class \<^class>\<open>semigroup\<close>:\<close> |
31678 | 27 |
|
28 |
lemma assoc_left: |
|
61076 | 29 |
fixes x y z :: "'a::semigroup" |
31678 | 30 |
shows "x \<oplus> (y \<oplus> z) = (x \<oplus> y) \<oplus> z" |
31 |
using assoc by (rule sym) |
|
32 |
||
69597 | 33 |
text \<open>\noindent The \<^class>\<open>semigroup\<close> constraint on type \<^typ>\<open>'a\<close> restricts instantiations of \<^typ>\<open>'a\<close> to types of class |
34 |
\<^class>\<open>semigroup\<close> and during the proof enables us to use the fact |
|
31678 | 35 |
@{fact assoc} whose type parameter is itself constrained to class |
69597 | 36 |
\<^class>\<open>semigroup\<close>. The main advantage of classes is that theorems |
31682 | 37 |
can be proved in the abstract and freely reused for each instance. |
31678 | 38 |
|
39 |
On instantiation, we have to give a proof that the given operations |
|
67406 | 40 |
obey the class axioms:\<close> |
31678 | 41 |
|
42 |
instantiation nat :: semigroup |
|
43 |
begin |
|
44 |
||
45 |
instance proof |
|
46 |
||
67406 | 47 |
txt \<open>\noindent The proof opens with a default proof step, which for |
48 |
instance judgements invokes method @{method intro_classes}.\<close> |
|
10328 | 49 |
|
50 |
||
31678 | 51 |
fix m n q :: nat |
52 |
show "(m \<oplus> n) \<oplus> q = m \<oplus> (n \<oplus> q)" |
|
53 |
by (induct m) simp_all |
|
54 |
qed |
|
10328 | 55 |
|
31678 | 56 |
end |
10328 | 57 |
|
67406 | 58 |
text \<open>\noindent Again, the interesting things enter the stage with |
59 |
parametric types:\<close> |
|
31678 | 60 |
|
38325 | 61 |
instantiation prod :: (semigroup, semigroup) semigroup |
31678 | 62 |
begin |
10328 | 63 |
|
31678 | 64 |
instance proof |
61076 | 65 |
fix p\<^sub>1 p\<^sub>2 p\<^sub>3 :: "'a::semigroup \<times> 'b::semigroup" |
53015
a1119cf551e8
standardized symbols via "isabelle update_sub_sup", excluding src/Pure and src/Tools/WWW_Find;
wenzelm
parents:
48985
diff
changeset
|
66 |
show "p\<^sub>1 \<oplus> p\<^sub>2 \<oplus> p\<^sub>3 = p\<^sub>1 \<oplus> (p\<^sub>2 \<oplus> p\<^sub>3)" |
a1119cf551e8
standardized symbols via "isabelle update_sub_sup", excluding src/Pure and src/Tools/WWW_Find;
wenzelm
parents:
48985
diff
changeset
|
67 |
by (cases p\<^sub>1, cases p\<^sub>2, cases p\<^sub>3) (simp add: assoc) |
10328 | 68 |
|
67406 | 69 |
txt \<open>\noindent Associativity of product semigroups is established |
31678 | 70 |
using the hypothetical associativity @{fact assoc} of the type |
69597 | 71 |
components, which holds due to the \<^class>\<open>semigroup\<close> constraints |
31678 | 72 |
imposed on the type components by the @{command instance} proposition. |
73 |
Indeed, this pattern often occurs with parametric types and type |
|
67406 | 74 |
classes.\<close> |
10420 | 75 |
|
31678 | 76 |
qed |
10328 | 77 |
|
31678 | 78 |
end |
79 |
||
67406 | 80 |
subsubsection \<open>Monoids\<close> |
10328 | 81 |
|
69505 | 82 |
text \<open>We define a subclass \<open>monoidl\<close> (a semigroup with a |
69597 | 83 |
left-hand neutral) by extending \<^class>\<open>semigroup\<close> with one additional |
69505 | 84 |
parameter \<open>neutral\<close> together with its property:\<close> |
10328 | 85 |
|
31678 | 86 |
class monoidl = semigroup + |
87 |
fixes neutral :: "'a" ("\<zero>") |
|
88 |
assumes neutl: "\<zero> \<oplus> x = x" |
|
10328 | 89 |
|
67406 | 90 |
text \<open>\noindent Again, we prove some instances, by providing |
31678 | 91 |
suitable parameter definitions and proofs for the additional |
67406 | 92 |
specifications.\<close> |
10328 | 93 |
|
31678 | 94 |
instantiation nat :: monoidl |
95 |
begin |
|
10328 | 96 |
|
31678 | 97 |
definition |
61076 | 98 |
neutral_nat_def: "\<zero> = (0::nat)" |
10328 | 99 |
|
31678 | 100 |
instance proof |
101 |
fix n :: nat |
|
102 |
show "\<zero> \<oplus> n = n" |
|
103 |
unfolding neutral_nat_def by simp |
|
104 |
qed |
|
10328 | 105 |
|
31678 | 106 |
end |
10328 | 107 |
|
67406 | 108 |
text \<open>\noindent In contrast to the examples above, we here have both |
31678 | 109 |
specification of class operations and a non-trivial instance proof. |
110 |
||
111 |
This covers products as well: |
|
67406 | 112 |
\<close> |
10328 | 113 |
|
38325 | 114 |
instantiation prod :: (monoidl, monoidl) monoidl |
31678 | 115 |
begin |
10328 | 116 |
|
31678 | 117 |
definition |
118 |
neutral_prod_def: "\<zero> = (\<zero>, \<zero>)" |
|
10328 | 119 |
|
31678 | 120 |
instance proof |
61076 | 121 |
fix p :: "'a::monoidl \<times> 'b::monoidl" |
31678 | 122 |
show "\<zero> \<oplus> p = p" |
123 |
by (cases p) (simp add: neutral_prod_def neutl) |
|
124 |
qed |
|
10328 | 125 |
|
31678 | 126 |
end |
10328 | 127 |
|
67406 | 128 |
text \<open>\noindent Fully-fledged monoids are modelled by another |
31678 | 129 |
subclass which does not add new parameters but tightens the |
67406 | 130 |
specification:\<close> |
10328 | 131 |
|
31678 | 132 |
class monoid = monoidl + |
133 |
assumes neutr: "x \<oplus> \<zero> = x" |
|
10328 | 134 |
|
69597 | 135 |
text \<open>\noindent Corresponding instances for \<^typ>\<open>nat\<close> and products |
67406 | 136 |
are left as an exercise to the reader.\<close> |
31678 | 137 |
|
67406 | 138 |
subsubsection \<open>Groups\<close> |
10328 | 139 |
|
69505 | 140 |
text \<open>\noindent To finish our small algebra example, we add a \<open>group\<close> class:\<close> |
10328 | 141 |
|
31678 | 142 |
class group = monoidl + |
143 |
fixes inv :: "'a \<Rightarrow> 'a" ("\<div> _" [81] 80) |
|
144 |
assumes invl: "\<div> x \<oplus> x = \<zero>" |
|
11196 | 145 |
|
67406 | 146 |
text \<open>\noindent We continue with a further example for abstract |
147 |
proofs relative to type classes:\<close> |
|
11196 | 148 |
|
31678 | 149 |
lemma left_cancel: |
61076 | 150 |
fixes x y z :: "'a::group" |
31678 | 151 |
shows "x \<oplus> y = x \<oplus> z \<longleftrightarrow> y = z" |
152 |
proof |
|
153 |
assume "x \<oplus> y = x \<oplus> z" |
|
154 |
then have "\<div> x \<oplus> (x \<oplus> y) = \<div> x \<oplus> (x \<oplus> z)" by simp |
|
155 |
then have "(\<div> x \<oplus> x) \<oplus> y = (\<div> x \<oplus> x) \<oplus> z" by (simp add: assoc) |
|
156 |
then show "y = z" by (simp add: invl neutl) |
|
157 |
next |
|
158 |
assume "y = z" |
|
159 |
then show "x \<oplus> y = x \<oplus> z" by simp |
|
160 |
qed |
|
10328 | 161 |
|
69505 | 162 |
text \<open>\noindent Any \<open>group\<close> is also a \<open>monoid\<close>; this |
31678 | 163 |
can be made explicit by claiming an additional subclass relation, |
67406 | 164 |
together with a proof of the logical difference:\<close> |
10328 | 165 |
|
31678 | 166 |
instance group \<subseteq> monoid |
167 |
proof |
|
168 |
fix x |
|
169 |
from invl have "\<div> x \<oplus> x = \<zero>" . |
|
170 |
then have "\<div> x \<oplus> (x \<oplus> \<zero>) = \<div> x \<oplus> x" |
|
171 |
by (simp add: neutl invl assoc [symmetric]) |
|
172 |
then show "x \<oplus> \<zero> = x" by (simp add: left_cancel) |
|
173 |
qed |
|
10396 | 174 |
|
67406 | 175 |
text \<open>\noindent The proof result is propagated to the type system, |
69505 | 176 |
making \<open>group\<close> an instance of \<open>monoid\<close> by adding an |
31678 | 177 |
additional edge to the graph of subclass relation; see also |
10396 | 178 |
Figure~\ref{fig:subclass}. |
179 |
||
180 |
\begin{figure}[htbp] |
|
31678 | 181 |
\begin{center} |
182 |
\small |
|
183 |
\unitlength 0.6mm |
|
184 |
\begin{picture}(40,60)(0,0) |
|
69505 | 185 |
\put(20,60){\makebox(0,0){\<open>semigroup\<close>}} |
186 |
\put(20,40){\makebox(0,0){\<open>monoidl\<close>}} |
|
187 |
\put(00,20){\makebox(0,0){\<open>monoid\<close>}} |
|
188 |
\put(40,00){\makebox(0,0){\<open>group\<close>}} |
|
31678 | 189 |
\put(20,55){\vector(0,-1){10}} |
190 |
\put(15,35){\vector(-1,-1){10}} |
|
191 |
\put(25,35){\vector(1,-3){10}} |
|
192 |
\end{picture} |
|
193 |
\hspace{8em} |
|
194 |
\begin{picture}(40,60)(0,0) |
|
69505 | 195 |
\put(20,60){\makebox(0,0){\<open>semigroup\<close>}} |
196 |
\put(20,40){\makebox(0,0){\<open>monoidl\<close>}} |
|
197 |
\put(00,20){\makebox(0,0){\<open>monoid\<close>}} |
|
198 |
\put(40,00){\makebox(0,0){\<open>group\<close>}} |
|
31678 | 199 |
\put(20,55){\vector(0,-1){10}} |
200 |
\put(15,35){\vector(-1,-1){10}} |
|
201 |
\put(05,15){\vector(3,-1){30}} |
|
202 |
\end{picture} |
|
203 |
\caption{Subclass relationship of monoids and groups: |
|
204 |
before and after establishing the relationship |
|
69505 | 205 |
\<open>group \<subseteq> monoid\<close>; transitive edges are left out.} |
31678 | 206 |
\label{fig:subclass} |
207 |
\end{center} |
|
10396 | 208 |
\end{figure} |
67406 | 209 |
\<close> |
10396 | 210 |
|
67406 | 211 |
subsubsection \<open>Inconsistencies\<close> |
10328 | 212 |
|
67406 | 213 |
text \<open>The reader may be wondering what happens if we attach an |
31678 | 214 |
inconsistent set of axioms to a class. So far we have always avoided |
215 |
to add new axioms to HOL for fear of inconsistencies and suddenly it |
|
10328 | 216 |
seems that we are throwing all caution to the wind. So why is there no |
217 |
problem? |
|
218 |
||
31678 | 219 |
The point is that by construction, all type variables in the axioms of |
220 |
a \isacommand{class} are automatically constrained with the class |
|
221 |
being defined (as shown for axiom @{thm[source]refl} above). These |
|
222 |
constraints are always carried around and Isabelle takes care that |
|
223 |
they are never lost, unless the type variable is instantiated with a |
|
224 |
type that has been shown to belong to that class. Thus you may be able |
|
69597 | 225 |
to prove \<^prop>\<open>False\<close> from your axioms, but Isabelle will remind you |
31678 | 226 |
that this theorem has the hidden hypothesis that the class is |
227 |
non-empty. |
|
228 |
||
229 |
Even if each individual class is consistent, intersections of |
|
230 |
(unrelated) classes readily become inconsistent in practice. Now we |
|
67406 | 231 |
know this need not worry us.\<close> |
31678 | 232 |
|
233 |
||
67406 | 234 |
subsubsection\<open>Syntactic Classes and Predefined Overloading\<close> |
12332 | 235 |
|
67406 | 236 |
text \<open>In our algebra example, we have started with a \emph{syntactic |
69597 | 237 |
class} \<^class>\<open>plus\<close> which only specifies operations but no axioms; it |
238 |
would have been also possible to start immediately with class \<^class>\<open>semigroup\<close>, specifying the \<open>\<oplus>\<close> operation and associativity at |
|
31678 | 239 |
the same time. |
10328 | 240 |
|
31678 | 241 |
Which approach is more appropriate depends. Usually it is more |
242 |
convenient to introduce operations and axioms in the same class: then |
|
243 |
the type checker will automatically insert the corresponding class |
|
244 |
constraints whenever the operations occur, reducing the need of manual |
|
245 |
annotations. However, when operations are decorated with popular |
|
246 |
syntax, syntactic classes can be an option to re-use the syntax in |
|
247 |
different contexts; this is indeed the way most overloaded constants |
|
248 |
in HOL are introduced, of which the most important are listed in |
|
249 |
Table~\ref{tab:overloading} in the appendix. Section |
|
250 |
\ref{sec:numeric-classes} covers a range of corresponding classes |
|
251 |
\emph{with} axioms. |
|
10328 | 252 |
|
31678 | 253 |
Further note that classes may contain axioms but \emph{no} operations. |
69597 | 254 |
An example is class \<^class>\<open>finite\<close> from theory \<^theory>\<open>HOL.Finite_Set\<close> |
61076 | 255 |
which specifies a type to be finite: @{lemma [source] "finite (UNIV :: 'a::finite |
67406 | 256 |
set)" by (fact finite_UNIV)}.\<close> |
31678 | 257 |
|
10328 | 258 |
(*<*)end(*>*) |