108 algebra \cite{Nipkow-Prehofer:1993,nipkow-sorts93,Wenzel:1997:TPHOL}. |
108 algebra \cite{Nipkow-Prehofer:1993,nipkow-sorts93,Wenzel:1997:TPHOL}. |
109 |
109 |
110 From a software enigineering point of view, type classes |
110 From a software enigineering point of view, type classes |
111 correspond to interfaces in object-oriented languages like Java; |
111 correspond to interfaces in object-oriented languages like Java; |
112 so, it is naturally desirable that type classes do not only |
112 so, it is naturally desirable that type classes do not only |
113 provide functions (class operations) but also state specifications |
113 provide functions (class parameters) but also state specifications |
114 implementations must obey. For example, the @{text "class eq"} |
114 implementations must obey. For example, the @{text "class eq"} |
115 above could be given the following specification, demanding that |
115 above could be given the following specification, demanding that |
116 @{text "class eq"} is an equivalence relation obeying reflexivity, |
116 @{text "class eq"} is an equivalence relation obeying reflexivity, |
117 symmetry and transitivity: |
117 symmetry and transitivity: |
118 |
118 |
128 SML functors \cite{classes_modules}. |
128 SML functors \cite{classes_modules}. |
129 Isabelle/Isar offers a discipline of type classes which brings |
129 Isabelle/Isar offers a discipline of type classes which brings |
130 all those aspects together: |
130 all those aspects together: |
131 |
131 |
132 \begin{enumerate} |
132 \begin{enumerate} |
133 \item specifying abstract operations togehter with |
133 \item specifying abstract parameters together with |
134 corresponding specifications, |
134 corresponding specifications, |
135 \item instantating those abstract operations by a particular |
135 \item instantating those abstract parameters by a particular |
136 type |
136 type |
137 \item in connection with a ``less ad-hoc'' approach to overloading, |
137 \item in connection with a ``less ad-hoc'' approach to overloading, |
138 \item with a direct link to the Isabelle module system |
138 \item with a direct link to the Isabelle module system |
139 (aka locales \cite{kammueller-locales}). |
139 (aka locales \cite{kammueller-locales}). |
140 \end{enumerate} |
140 \end{enumerate} |
157 |
157 |
158 subsection {* Class definition *} |
158 subsection {* Class definition *} |
159 |
159 |
160 text {* |
160 text {* |
161 Depending on an arbitrary type @{text "\<alpha>"}, class @{text |
161 Depending on an arbitrary type @{text "\<alpha>"}, class @{text |
162 "semigroup"} introduces a binary operation @{text "\<circ>"} that is |
162 "semigroup"} introduces a binary operator @{text "\<otimes>"} that is |
163 assumed to be associative: |
163 assumed to be associative: |
164 *} |
164 *} |
165 |
165 |
166 class semigroup = type + |
166 class semigroup = type + |
167 fixes mult :: "\<alpha> \<Rightarrow> \<alpha> \<Rightarrow> \<alpha>" (infixl "\<^loc>\<otimes>" 70) |
167 fixes mult :: "\<alpha> \<Rightarrow> \<alpha> \<Rightarrow> \<alpha>" (infixl "\<^loc>\<otimes>" 70) |
168 assumes assoc: "(x \<^loc>\<otimes> y) \<^loc>\<otimes> z = x \<^loc>\<otimes> (y \<^loc>\<otimes> z)" |
168 assumes assoc: "(x \<^loc>\<otimes> y) \<^loc>\<otimes> z = x \<^loc>\<otimes> (y \<^loc>\<otimes> z)" |
169 |
169 |
170 text {* |
170 text {* |
171 \noindent This @{text "\<CLASS>"} specification consists of two |
171 \noindent This @{text "\<CLASS>"} specification consists of two |
172 parts: the \qn{operational} part names the class operation (@{text |
172 parts: the \qn{operational} part names the class parameter (@{text |
173 "\<FIXES>"}), the \qn{logical} part specifies properties on them |
173 "\<FIXES>"}), the \qn{logical} part specifies properties on them |
174 (@{text "\<ASSUMES>"}). The local @{text "\<FIXES>"} and @{text |
174 (@{text "\<ASSUMES>"}). The local @{text "\<FIXES>"} and @{text |
175 "\<ASSUMES>"} are lifted to the theory toplevel, yielding the global |
175 "\<ASSUMES>"} are lifted to the theory toplevel, yielding the global |
176 operation @{term [source] "mult \<Colon> \<alpha>\<Colon>semigroup \<Rightarrow> \<alpha> \<Rightarrow> \<alpha>"} and the |
176 parameter @{term [source] "mult \<Colon> \<alpha>\<Colon>semigroup \<Rightarrow> \<alpha> \<Rightarrow> \<alpha>"} and the |
177 global theorem @{text "semigroup.assoc:"}~@{prop [source] "\<And>x y |
177 global theorem @{text "semigroup.assoc:"}~@{prop [source] "\<And>x y |
178 z \<Colon> \<alpha>\<Colon>semigroup. (x \<otimes> y) \<otimes> z = x \<otimes> (y \<otimes> z)"}. |
178 z \<Colon> \<alpha>\<Colon>semigroup. (x \<otimes> y) \<otimes> z = x \<otimes> (y \<otimes> z)"}. |
179 *} |
179 *} |
180 |
180 |
181 |
181 |
182 subsection {* Class instantiation \label{sec:class_inst} *} |
182 subsection {* Class instantiation \label{sec:class_inst} *} |
183 |
183 |
184 text {* |
184 text {* |
185 The concrete type @{text "int"} is made a @{text "semigroup"} |
185 The concrete type @{text "int"} is made a @{text "semigroup"} |
186 instance by providing a suitable definition for the class operation |
186 instance by providing a suitable definition for the class parameter |
187 @{text "mult"} and a proof for the specification of @{text "assoc"}. |
187 @{text "mult"} and a proof for the specification of @{text "assoc"}. |
188 *} |
188 *} |
189 |
189 |
190 instance int :: semigroup |
190 instance int :: semigroup |
191 mult_int_def: "i \<otimes> j \<equiv> i + j" |
191 mult_int_def: "i \<otimes> j \<equiv> i + j" |
235 subsection {* Subclasses *} |
235 subsection {* Subclasses *} |
236 |
236 |
237 text {* |
237 text {* |
238 We define a subclass @{text "monoidl"} (a semigroup with a left-hand neutral) |
238 We define a subclass @{text "monoidl"} (a semigroup with a left-hand neutral) |
239 by extending @{text "semigroup"} |
239 by extending @{text "semigroup"} |
240 with one additional operation @{text "neutral"} together |
240 with one additional parameter @{text "neutral"} together |
241 with its property: |
241 with its property: |
242 *} |
242 *} |
243 |
243 |
244 class monoidl = semigroup + |
244 class monoidl = semigroup + |
245 fixes neutral :: "\<alpha>" ("\<^loc>\<one>") |
245 fixes neutral :: "\<alpha>" ("\<^loc>\<one>") |
246 assumes neutl: "\<^loc>\<one> \<^loc>\<otimes> x = x" |
246 assumes neutl: "\<^loc>\<one> \<^loc>\<otimes> x = x" |
247 |
247 |
248 text {* |
248 text {* |
249 \noindent Again, we make some instances, by |
249 \noindent Again, we make some instances, by |
250 providing suitable operation definitions and proofs for the |
250 providing suitable parameter definitions and proofs for the |
251 additional specifications. |
251 additional specifications. |
252 *} |
252 *} |
253 |
253 |
254 instance nat :: monoidl |
254 instance nat :: monoidl |
255 neutral_nat_def: "\<one> \<equiv> 0" |
255 neutral_nat_def: "\<one> \<equiv> 0" |
427 definitions you may use any specification tool |
427 definitions you may use any specification tool |
428 which works together with locales (e.g. \cite{krauss2006}). |
428 which works together with locales (e.g. \cite{krauss2006}). |
429 *} |
429 *} |
430 |
430 |
431 |
431 |
432 (*subsection {* Additional subclass relations *} |
432 subsection {* Additional subclass relations *} |
433 |
433 |
434 text {* |
434 text {* |
435 Any @{text "group"} is also a @{text "monoid"}; this |
435 Any @{text "group"} is also a @{text "monoid"}; this |
436 can be made explicit by claiming an additional subclass relation, |
436 can be made explicit by claiming an additional subclass relation, |
437 together with a proof of the logical difference: |
437 together with a proof of the logical difference: |
438 *} |
438 *} |
439 |
439 |
440 instance advanced group < monoid |
440 subclass (in group) monoid |
441 proof unfold_locales |
441 proof unfold_locales |
442 fix x |
442 fix x |
443 from invl have "x\<^loc>\<div> \<^loc>\<otimes> x = \<^loc>\<one>" by simp |
443 from invl have "x\<^loc>\<div> \<^loc>\<otimes> x = \<^loc>\<one>" by simp |
444 with assoc [symmetric] neutl invl have "x\<^loc>\<div> \<^loc>\<otimes> (x \<^loc>\<otimes> \<^loc>\<one>) = x\<^loc>\<div> \<^loc>\<otimes> x" by simp |
444 with assoc [symmetric] neutl invl have "x\<^loc>\<div> \<^loc>\<otimes> (x \<^loc>\<otimes> \<^loc>\<one>) = x\<^loc>\<div> \<^loc>\<otimes> x" by simp |
445 with left_cancel show "x \<^loc>\<otimes> \<^loc>\<one> = x" by simp |
445 with left_cancel show "x \<^loc>\<otimes> \<^loc>\<one> = x" by simp |
450 and thus conveniently is opened using the @{text unfold_locales} |
450 and thus conveniently is opened using the @{text unfold_locales} |
451 method which only leaves the logical differences still |
451 method which only leaves the logical differences still |
452 open to proof to the user. After the proof it is propagated |
452 open to proof to the user. After the proof it is propagated |
453 to the type system, making @{text group} an instance of |
453 to the type system, making @{text group} an instance of |
454 @{text monoid}. For illustration, a derived definition |
454 @{text monoid}. For illustration, a derived definition |
455 in @{text group} which uses @{text of_nat}: |
455 in @{text group} which uses @{text pow_nat}: |
456 *} |
456 *} |
457 |
457 |
458 definition (in group) |
458 definition (in group) |
459 pow_int :: "int \<Rightarrow> \<alpha> \<Rightarrow> \<alpha>" where |
459 pow_int :: "int \<Rightarrow> \<alpha> \<Rightarrow> \<alpha>" where |
460 "pow_int k x = (if k >= 0 |
460 "pow_int k x = (if k >= 0 |
463 |
463 |
464 text {* |
464 text {* |
465 yields the global definition of |
465 yields the global definition of |
466 @{term [source] "pow_int \<Colon> int \<Rightarrow> \<alpha>\<Colon>group \<Rightarrow> \<alpha>\<Colon>group"} |
466 @{term [source] "pow_int \<Colon> int \<Rightarrow> \<alpha>\<Colon>group \<Rightarrow> \<alpha>\<Colon>group"} |
467 with the corresponding theorem @{thm pow_int_def [no_vars]}. |
467 with the corresponding theorem @{thm pow_int_def [no_vars]}. |
468 *} *) |
468 *} |
469 |
469 |
470 |
470 |
471 section {* Further issues *} |
471 section {* Further issues *} |
472 |
472 |
473 subsection {* Code generation *} |
473 subsection {* Code generation *} |
482 lacking type classes (e.g.~SML), type classes |
482 lacking type classes (e.g.~SML), type classes |
483 are implemented by explicit dictionary construction. |
483 are implemented by explicit dictionary construction. |
484 For example, lets go back to the power function: |
484 For example, lets go back to the power function: |
485 *} |
485 *} |
486 |
486 |
487 fun |
487 (* fun |
488 pow_nat :: "nat \<Rightarrow> \<alpha>\<Colon>group \<Rightarrow> \<alpha>\<Colon>group" where |
488 pow_nat :: "nat \<Rightarrow> \<alpha>\<Colon>group \<Rightarrow> \<alpha>\<Colon>group" where |
489 "pow_nat 0 x = \<one>" |
489 "pow_nat 0 x = \<one>" |
490 | "pow_nat (Suc n) x = x \<otimes> pow_nat n x" |
490 | "pow_nat (Suc n) x = x \<otimes> pow_nat n x" |
491 |
491 |
492 definition |
492 definition |
493 pow_int :: "int \<Rightarrow> \<alpha>\<Colon>group \<Rightarrow> \<alpha>\<Colon>group" where |
493 pow_int :: "int \<Rightarrow> \<alpha>\<Colon>group \<Rightarrow> \<alpha>\<Colon>group" where |
494 "pow_int k x = (if k >= 0 |
494 "pow_int k x = (if k >= 0 |
495 then pow_nat (nat k) x |
495 then pow_nat (nat k) x |
496 else (pow_nat (nat (- k)) x)\<div>)" |
496 else (pow_nat (nat (- k)) x)\<div>)"*) |
497 |
497 |
498 definition |
498 definition |
499 example :: int where |
499 example :: int where |
500 "example = pow_int 10 (-2)" |
500 "example = pow_int 10 (-2)" |
501 |
501 |