diff -r 44d9d55b9ef4 -r 3c3f8b182e4b src/Doc/Classes/Classes.thy --- a/src/Doc/Classes/Classes.thy Mon Oct 12 21:11:48 2015 +0200 +++ b/src/Doc/Classes/Classes.thy Mon Oct 12 21:15:10 2015 +0200 @@ -2,9 +2,9 @@ imports Main Setup begin -section {* Introduction *} +section \Introduction\ -text {* +text \ Type classes were introduced by Wadler and Blott @{cite wadler89how} into the Haskell language to allow for a reasonable implementation of overloading\footnote{throughout this tutorial, we are referring @@ -89,23 +89,23 @@ algebraic hierarchy of semigroups, monoids and groups. Our background theory is that of Isabelle/HOL @{cite "isa-tutorial"}, for which some familiarity is assumed. -*} +\ -section {* A simple algebra example \label{sec:example} *} +section \A simple algebra example \label{sec:example}\ -subsection {* Class definition *} +subsection \Class definition\ -text {* +text \ Depending on an arbitrary type @{text "\"}, class @{text "semigroup"} introduces a binary operator @{text "(\)"} that is assumed to be associative: -*} +\ class %quote semigroup = fixes mult :: "\ \ \ \ \" (infixl "\" 70) assumes assoc: "(x \ y) \ z = x \ (y \ z)" -text {* +text \ \noindent This @{command class} specification consists of two parts: the \qn{operational} part names the class parameter (@{element "fixes"}), the \qn{logical} part specifies properties on them @@ -114,17 +114,17 @@ parameter @{term [source] "mult :: \::semigroup \ \ \ \"} and the global theorem @{fact "semigroup.assoc:"}~@{prop [source] "\x y z :: \::semigroup. (x \ y) \ z = x \ (y \ z)"}. -*} +\ -subsection {* Class instantiation \label{sec:class_inst} *} +subsection \Class instantiation \label{sec:class_inst}\ -text {* +text \ The concrete type @{typ int} is made a @{class semigroup} instance by providing a suitable definition for the class parameter @{text "(\)"} and a proof for the specification of @{fact assoc}. This is accomplished by the @{command instantiation} target: -*} +\ instantiation %quote int :: semigroup begin @@ -140,7 +140,7 @@ end %quote -text {* +text \ \noindent @{command instantiation} defines class parameters at a particular instance using common specification tools (here, @{command definition}). The concluding @{command instance} opens a @@ -157,7 +157,7 @@ \medskip Another instance of @{class semigroup} yields the natural numbers: -*} +\ instantiation %quote nat :: semigroup begin @@ -174,21 +174,21 @@ end %quote -text {* +text \ \noindent Note the occurrence of the name @{text mult_nat} in the primrec declaration; by default, the local name of a class operation @{text f} to be instantiated on type constructor @{text \} is mangled as @{text f_\}. In case of uncertainty, these names may be inspected using the @{command "print_context"} command. -*} +\ -subsection {* Lifting and parametric types *} +subsection \Lifting and parametric types\ -text {* +text \ Overloaded definitions given at a class instantiation may include recursion over the syntactic structure of types. As a canonical example, we model product semigroups using our simple algebra: -*} +\ instantiation %quote prod :: (semigroup, semigroup) semigroup begin @@ -204,34 +204,34 @@ end %quote -text {* +text \ \noindent Associativity of product semigroups is established using the definition of @{text "(\)"} on products and the hypothetical associativity of the type components; these hypotheses are legitimate due to the @{class semigroup} constraints imposed on the type components by the @{command instance} proposition. Indeed, this pattern often occurs with parametric types and type classes. -*} +\ -subsection {* Subclassing *} +subsection \Subclassing\ -text {* +text \ We define a subclass @{text monoidl} (a semigroup with a left-hand neutral) by extending @{class semigroup} with one additional parameter @{text neutral} together with its characteristic property: -*} +\ class %quote monoidl = semigroup + fixes neutral :: "\" ("\") assumes neutl: "\ \ x = x" -text {* +text \ \noindent Again, we prove some instances, by providing suitable parameter definitions and proofs for the additional specifications. Observe that instantiations for types with the same arity may be simultaneous: -*} +\ instantiation %quote nat and int :: monoidl begin @@ -268,10 +268,10 @@ end %quote -text {* +text \ \noindent Fully-fledged monoids are modelled by another subclass, which does not add new parameters but tightens the specification: -*} +\ class %quote monoid = monoidl + assumes neutr: "x \ \ = x" @@ -302,10 +302,10 @@ end %quote -text {* +text \ \noindent To finish our small algebra example, we add a @{text group} class with a corresponding instance: -*} +\ class %quote group = monoidl + fixes inverse :: "\ \ \" ("(_\
)" [1000] 999) @@ -327,57 +327,57 @@ end %quote -section {* Type classes as locales *} +section \Type classes as locales\ -subsection {* A look behind the scenes *} +subsection \A look behind the scenes\ -text {* +text \ The example above gives an impression how Isar type classes work in practice. As stated in the introduction, classes also provide a link to Isar's locale system. Indeed, the logical core of a class is nothing other than a locale: -*} +\ class %quote idem = fixes f :: "\ \ \" assumes idem: "f (f x) = f x" -text {* +text \ \noindent essentially introduces the locale -*} (*<*)setup %invisible {* Sign.add_path "foo" *} +\ (*<*)setup %invisible \Sign.add_path "foo"\ (*>*) locale %quote idem = fixes f :: "\ \ \" assumes idem: "f (f x) = f x" -text {* \noindent together with corresponding constant(s): *} +text \\noindent together with corresponding constant(s):\ consts %quote f :: "\ \ \" -text {* +text \ \noindent The connection to the type system is done by means of a primitive type class @{text "idem"}, together with a corresponding interpretation: -*} +\ interpretation %quote idem_class: idem "f :: (\::idem) \ \" (*<*)sorry(*>*) -text {* +text \ \noindent This gives you the full power of the Isabelle module system; conclusions in locale @{text idem} are implicitly propagated to class @{text idem}. -*} (*<*)setup %invisible {* Sign.parent_path *} +\ (*<*)setup %invisible \Sign.parent_path\ (*>*) -subsection {* Abstract reasoning *} +subsection \Abstract reasoning\ -text {* +text \ Isabelle locales enable reasoning at a general level, while results are implicitly transferred to all instances. For example, we can now establish the @{text "left_cancel"} lemma for groups, which states that the function @{text "(x \)"} is injective: -*} +\ lemma %quote (in group) left_cancel: "x \ y = x \ z \ y = z" proof @@ -390,7 +390,7 @@ then show "x \ y = x \ z" by simp qed -text {* +text \ \noindent Here the \qt{@{keyword "in"} @{class group}} target specification indicates that the result is recorded within that context for later use. This local theorem is also lifted to the @@ -399,20 +399,20 @@ made an instance of @{text "group"} before, we may refer to that fact as well: @{prop [source] "\x y z :: int. x \ y = x \ z \ y = z"}. -*} +\ -subsection {* Derived definitions *} +subsection \Derived definitions\ -text {* +text \ Isabelle locales are targets which support local definitions: -*} +\ primrec %quote (in monoid) pow_nat :: "nat \ \ \ \" where "pow_nat 0 x = \" | "pow_nat (Suc n) x = x \ pow_nat n x" -text {* +text \ \noindent If the locale @{text group} is also a class, this local definition is propagated onto a global definition of @{term [source] "pow_nat :: nat \ \::monoid \ \::monoid"} with corresponding theorems @@ -423,12 +423,12 @@ you may use any specification tool which works together with locales, such as Krauss's recursive function package @{cite krauss2006}. -*} +\ -subsection {* A functor analogy *} +subsection \A functor analogy\ -text {* +text \ We introduced Isar classes by analogy to type classes in functional programming; if we reconsider this in the context of what has been said about type classes and locales, we can drive this analogy @@ -440,18 +440,18 @@ lists the same operations as for genuinely algebraic types. In such a case, we can simply make a particular interpretation of monoids for lists: -*} +\ interpretation %quote list_monoid: monoid append "[]" proof qed auto -text {* +text \ \noindent This enables us to apply facts on monoids to lists, e.g. @{thm list_monoid.neutl [no_vars]}. When using this interpretation pattern, it may also be appropriate to map derived definitions accordingly: -*} +\ primrec %quote replicate :: "nat \ \ list \ \ list" where "replicate 0 _ = []" @@ -469,7 +469,7 @@ qed qed intro_locales -text {* +text \ \noindent This pattern is also helpful to reuse abstract specifications on the \emph{same} type. For example, think of a class @{text preorder}; for type @{typ nat}, there are at least two @@ -478,15 +478,15 @@ @{command instantiation}; using the locale behind the class @{text preorder}, it is still possible to utilise the same abstract specification again using @{command interpretation}. -*} +\ -subsection {* Additional subclass relations *} +subsection \Additional subclass relations\ -text {* +text \ Any @{text "group"} is also a @{text "monoid"}; this can be made explicit by claiming an additional subclass relation, together with a proof of the logical difference: -*} +\ subclass %quote (in group) monoid proof @@ -496,7 +496,7 @@ with left_cancel show "x \ \ = x" by simp qed -text {* +text \ The logical proof is carried out on the locale level. Afterwards it is propagated to the type system, making @{text group} an instance of @{text monoid} by adding an additional edge to the graph of @@ -534,50 +534,50 @@ For illustration, a derived definition in @{text group} using @{text pow_nat} -*} +\ definition %quote (in group) pow_int :: "int \ \ \ \" where "pow_int k x = (if k >= 0 then pow_nat (nat k) x else (pow_nat (nat (- k)) x)\
)" -text {* +text \ \noindent yields the global definition of @{term [source] "pow_int :: int \ \::group \ \::group"} with the corresponding theorem @{thm pow_int_def [no_vars]}. -*} +\ -subsection {* A note on syntax *} +subsection \A note on syntax\ -text {* +text \ As a convenience, class context syntax allows references to local class operations and their global counterparts uniformly; type inference resolves ambiguities. For example: -*} +\ context %quote semigroup begin -term %quote "x \ y" -- {* example 1 *} -term %quote "(x::nat) \ y" -- {* example 2 *} +term %quote "x \ y" -- \example 1\ +term %quote "(x::nat) \ y" -- \example 2\ end %quote -term %quote "x \ y" -- {* example 3 *} +term %quote "x \ y" -- \example 3\ -text {* +text \ \noindent Here in example 1, the term refers to the local class operation @{text "mult [\]"}, whereas in example 2 the type constraint enforces the global class operation @{text "mult [nat]"}. In the global context in example 3, the reference is to the polymorphic global class operation @{text "mult [?\ :: semigroup]"}. -*} +\ -section {* Further issues *} +section \Further issues\ -subsection {* Type classes and code generation *} +subsection \Type classes and code generation\ -text {* +text \ Turning back to the first motivation for type classes, namely overloading, it is obvious that overloading stemming from @{command class} statements and @{command instantiation} targets naturally @@ -586,37 +586,37 @@ language (e.g.~SML) lacks type classes, then they are implemented by an explicit dictionary construction. As example, let's go back to the power function: -*} +\ definition %quote example :: int where "example = pow_int 10 (-2)" -text {* +text \ \noindent This maps to Haskell as follows: -*} -text %quotetypewriter {* +\ +text %quotetypewriter \ @{code_stmts example (Haskell)} -*} +\ -text {* +text \ \noindent The code in SML has explicit dictionary passing: -*} -text %quotetypewriter {* +\ +text %quotetypewriter \ @{code_stmts example (SML)} -*} +\ -text {* +text \ \noindent In Scala, implicits are used as dictionaries: -*} -text %quotetypewriter {* +\ +text %quotetypewriter \ @{code_stmts example (Scala)} -*} +\ -subsection {* Inspecting the type class universe *} +subsection \Inspecting the type class universe\ -text {* +text \ To facilitate orientation in complex subclass structures, two diagnostics commands are provided: @@ -631,7 +631,7 @@ an optional second sort argument to all superclasses of this sort. \end{description} -*} +\ end