diff options
Diffstat (limited to 'doc/refman/Classes.tex')
-rw-r--r-- | doc/refman/Classes.tex | 412 |
1 files changed, 412 insertions, 0 deletions
diff --git a/doc/refman/Classes.tex b/doc/refman/Classes.tex new file mode 100644 index 00000000..7bd4f352 --- /dev/null +++ b/doc/refman/Classes.tex @@ -0,0 +1,412 @@ +\def\Haskell{\textsc{Haskell}\xspace} +\def\eol{\setlength\parskip{0pt}\par} +\def\indent#1{\noindent\kern#1} +\def\cst#1{\textsf{#1}} + +\newcommand\tele[1]{\overrightarrow{#1}} + +\achapter{\protect{Type Classes}} +\aauthor{Matthieu Sozeau} +\label{typeclasses} + +\begin{flushleft} + \em The status of Type Classes is (extremely) experimental. +\end{flushleft} + +This chapter presents a quick reference of the commands related to type +classes. For an actual introduction to type classes, there is a +description of the system \cite{sozeau08} and the literature on type +classes in \Haskell which also applies. + +\asection{Class and Instance declarations} +\label{ClassesInstances} + +The syntax for class and instance declarations is the same as +record syntax of \Coq: +\def\kw{\texttt} +\def\classid{\texttt} + +\begin{center} +\[\begin{array}{l} +\kw{Class}~\classid{Id}~(\alpha_1 : \tau_1) \cdots (\alpha_n : \tau_n) +[: \sort] := \{\\ +\begin{array}{p{0em}lcl} + & \cst{f}_1 & : & \type_1 ; \\ + & \vdots & & \\ + & \cst{f}_m & : & \type_m \}. +\end{array}\end{array}\] +\end{center} +\begin{center} +\[\begin{array}{l} +\kw{Instance}~\ident~:~\classid{Id}~\term_1 \cdots \term_n := \{\\ +\begin{array}{p{0em}lcl} + & \cst{f}_1 & := & \term_{f_1} ; \\ + & \vdots & & \\ + & \cst{f}_m & := & \term_{f_m} \}. +\end{array}\end{array}\] +\end{center} +\begin{coq_eval} + Reset Initial. + Generalizable All Variables. +\end{coq_eval} + +The $\tele{\alpha_i : \tau_i}$ variables are called the \emph{parameters} +of the class and the $\tele{f_k : \type_k}$ are called the +\emph{methods}. Each class definition gives rise to a corresponding +record declaration and each instance is a regular definition whose name +is given by $\ident$ and type is an instantiation of the record type. + +We'll use the following example class in the rest of the chapter: + +\begin{coq_example*} +Class EqDec (A : Type) := { + eqb : A -> A -> bool ; + eqb_leibniz : forall x y, eqb x y = true -> x = y }. +\end{coq_example*} + +This class implements a boolean equality test which is compatible with +Leibniz equality on some type. An example implementation is: + +\begin{coq_example*} +Instance unit_EqDec : EqDec unit := +{ eqb x y := true ; + eqb_leibniz x y H := + match x, y return x = y with tt, tt => refl_equal tt end }. +\end{coq_example*} + +If one does not give all the members in the \texttt{Instance} +declaration, Coq enters the proof-mode and the user is asked to build +inhabitants of the remaining fields, e.g.: + +\begin{coq_example*} +Instance eq_bool : EqDec bool := +{ eqb x y := if x then y else negb y }. +\end{coq_example*} +\begin{coq_example} +Proof. intros x y H. + destruct x ; destruct y ; (discriminate || reflexivity). +Defined. +\end{coq_example} + +One has to take care that the transparency of every field is determined +by the transparency of the \texttt{Instance} proof. One can use +alternatively the \texttt{Program} \texttt{Instance} \comindex{Program Instance} variant which has +richer facilities for dealing with obligations. + +\asection{Binding classes} + +Once a type class is declared, one can use it in class binders: +\begin{coq_example} +Definition neqb {A} {eqa : EqDec A} (x y : A) := negb (eqb x y). +\end{coq_example} + +When one calls a class method, a constraint is generated that is +satisfied only in contexts where the appropriate instances can be +found. In the example above, a constraint \texttt{EqDec A} is generated and +satisfied by \texttt{{eqa : EqDec A}}. In case no satisfying constraint can be +found, an error is raised: + +\begin{coq_example} +Definition neqb' (A : Type) (x y : A) := negb (eqb x y). +\end{coq_example} + +The algorithm used to solve constraints is a variant of the eauto tactic +that does proof search with a set of lemmas (the instances). It will use +local hypotheses as well as declared lemmas in the +\texttt{typeclass\_instances} database. Hence the example can also be +written: + +\begin{coq_example} +Definition neqb' A (eqa : EqDec A) (x y : A) := negb (eqb x y). +\end{coq_example} + +However, the generalizing binders should be used instead as they have +particular support for type classes: +\begin{itemize} +\item They automatically set the maximally implicit status for type + class arguments, making derived functions as easy to use as class + methods. In the example above, \texttt{A} and \texttt{eqa} should be + set maximally implicit. +\item They support implicit quantification on partialy applied type + classes (\S \ref{implicit-generalization}). + Any argument not given as part of a type class binder will be + automatically generalized. +\item They also support implicit quantification on superclasses + (\S \ref{classes:superclasses}) +\end{itemize} + +Following the previous example, one can write: +\begin{coq_example} +Definition neqb_impl `{eqa : EqDec A} (x y : A) := negb (eqb x y). +\end{coq_example} + +Here \texttt{A} is implicitly generalized, and the resulting function +is equivalent to the one above. + +\asection{Parameterized Instances} + +One can declare parameterized instances as in \Haskell simply by giving +the constraints as a binding context before the instance, e.g.: + +\begin{coq_example} +Instance prod_eqb `(EA : EqDec A, EB : EqDec B) : EqDec (A * B) := +{ eqb x y := match x, y with + | (la, ra), (lb, rb) => andb (eqb la lb) (eqb ra rb) + end }. +\end{coq_example} +\begin{coq_eval} +Admitted. +\end{coq_eval} + +These instances are used just as well as lemmas in the instance hint database. + +\asection{Sections and contexts} +\label{SectionContext} +To ease the parametrization of developments by type classes, we provide +a new way to introduce variables into section contexts, compatible with +the implicit argument mechanism. +The new command works similarly to the \texttt{Variables} vernacular +(see \ref{Variable}), except it accepts any binding context as argument. +For example: + +\begin{coq_example} +Section EqDec_defs. + Context `{EA : EqDec A}. +\end{coq_example} + +\begin{coq_example*} + Global Instance option_eqb : EqDec (option A) := + { eqb x y := match x, y with + | Some x, Some y => eqb x y + | None, None => true + | _, _ => false + end }. +\end{coq_example*} +\begin{coq_eval} +Proof. +intros x y ; destruct x ; destruct y ; intros H ; +try discriminate ; try apply eqb_leibniz in H ; +subst ; auto. +Defined. +\end{coq_eval} + +\begin{coq_example} +End EqDec_defs. +About option_eqb. +\end{coq_example} + +Here the \texttt{Global} modifier redeclares the instance at the end of +the section, once it has been generalized by the context variables it uses. + +\asection{Building hierarchies} + +\subsection{Superclasses} +\label{classes:superclasses} +One can also parameterize classes by other classes, generating a +hierarchy of classes and superclasses. In the same way, we give the +superclasses as a binding context: + +\begin{coq_example*} +Class Ord `(E : EqDec A) := + { le : A -> A -> bool }. +\end{coq_example*} + +Contrary to \Haskell, we have no special syntax for superclasses, but +this declaration is morally equivalent to: +\begin{verbatim} +Class `(E : EqDec A) => Ord A := + { le : A -> A -> bool }. +\end{verbatim} + +This declaration means that any instance of the \texttt{Ord} class must +have an instance of \texttt{EqDec}. The parameters of the subclass contain +at least all the parameters of its superclasses in their order of +appearance (here \texttt{A} is the only one). +As we have seen, \texttt{Ord} is encoded as a record type with two parameters: +a type \texttt{A} and an \texttt{E} of type \texttt{EqDec A}. However, one can +still use it as if it had a single parameter inside generalizing binders: the +generalization of superclasses will be done automatically. +\begin{coq_example*} +Definition le_eqb `{Ord A} (x y : A) := andb (le x y) (le y x). +\end{coq_example*} + +In some cases, to be able to specify sharing of structures, one may want to give +explicitly the superclasses. It is is possible to do it directly in regular +binders, and using the \texttt{!} modifier in class binders. For +example: +\begin{coq_example*} +Definition lt `{eqa : EqDec A, ! Ord eqa} (x y : A) := + andb (le x y) (neqb x y). +\end{coq_example*} + +The \texttt{!} modifier switches the way a binder is parsed back to the +regular interpretation of Coq. In particular, it uses the implicit +arguments mechanism if available, as shown in the example. + +\subsection{Substructures} + +Substructures are components of a class which are instances of a class +themselves. They often arise when using classes for logical properties, +e.g.: + +\begin{coq_eval} +Require Import Relations. +\end{coq_eval} +\begin{coq_example*} +Class Reflexive (A : Type) (R : relation A) := + reflexivity : forall x, R x x. +Class Transitive (A : Type) (R : relation A) := + transitivity : forall x y z, R x y -> R y z -> R x z. +\end{coq_example*} + +This declares singleton classes for reflexive and transitive relations, +(see \ref{SingletonClass} for an explanation). +These may be used as part of other classes: + +\begin{coq_example*} +Class PreOrder (A : Type) (R : relation A) := +{ PreOrder_Reflexive :> Reflexive A R ; + PreOrder_Transitive :> Transitive A R }. +\end{coq_example*} + +The syntax \texttt{:>} indicates that each \texttt{PreOrder} can be seen +as a \texttt{Reflexive} relation. So each time a reflexive relation is +needed, a preorder can be used instead. This is very similar to the +coercion mechanism of \texttt{Structure} declarations. +The implementation simply declares each projection as an instance. + +One can also declare existing objects or structure +projections using the \texttt{Existing Instance} command to achieve the +same effect. + +\section{Summary of the commands +\label{TypeClassCommands}} + +\subsection{\tt Class {\ident} {\binder$_1$ \ldots~\binder$_n$} + : \sort := \{ field$_1$ ; \ldots ; field$_k$ \}.} +\comindex{Class} +\label{Class} + +The \texttt{Class} command is used to declare a type class with +parameters {\binder$_1$} to {\binder$_n$} and fields {\tt field$_1$} to +{\tt field$_k$}. + +\begin{Variants} +\item \label{SingletonClass} {\tt Class {\ident} {\binder$_1$ \ldots \binder$_n$} + : \sort := \ident$_1$ : \type$_1$.} + This variant declares a \emph{singleton} class whose only method is + {\tt \ident$_1$}. This singleton class is a so-called definitional + class, represented simply as a definition + {\tt {\ident} \binder$_1$ \ldots \binder$_n$ := \type$_1$} and whose + instances are themselves objects of this type. Definitional classes + are not wrapped inside records, and the trivial projection of an + instance of such a class is convertible to the instance itself. This can + be useful to make instances of existing objects easily and to reduce + proof size by not inserting useless projections. The class + constant itself is declared rigid during resolution so that the class + abstraction is maintained. + +\item \label{ExistingClass} {\tt Existing Class {\ident}.\comindex{Existing Class}} + This variant declares a class a posteriori from a constant or + inductive definition. No methods or instances are defined. +\end{Variants} + +\subsection{\tt Instance {\ident} {\binder$_1$ \ldots \binder$_n$} : + {Class} {t$_1$ \ldots t$_n$} [| \textit{priority}] + := \{ field$_1$ := b$_1$ ; \ldots ; field$_i$ := b$_i$ \}} +\comindex{Instance} +\label{Instance} + +The \texttt{Instance} command is used to declare a type class instance +named {\ident} of the class \emph{Class} with parameters {t$_1$} to {t$_n$} and +fields {\tt b$_1$} to {\tt b$_i$}, where each field must be a declared +field of the class. Missing fields must be filled in interactive proof mode. + +An arbitrary context of the form {\tt \binder$_1$ \ldots \binder$_n$} +can be put after the name of the instance and before the colon to +declare a parameterized instance. +An optional \textit{priority} can be declared, 0 being the highest +priority as for auto hints. + +\begin{Variants} +\item {\tt Instance {\ident} {\binder$_1$ \ldots \binder$_n$} : + forall {\binder$_{n+1}$ \ldots \binder$_m$}, + {Class} {t$_1$ \ldots t$_n$} [| \textit{priority}] := \term} + This syntax is used for declaration of singleton class instances or + for directly giving an explicit term of type + {\tt forall {\binder$_{n+1}$ \ldots \binder$_m$}, {Class} {t$_1$ \ldots t$_n$}}. + One need not even mention the unique field name for singleton classes. + +\item {\tt Global Instance} One can use the \texttt{Global} modifier on + instances declared in a section so that their generalization is automatically + redeclared after the section is closed. + +\item {\tt Program Instance} \comindex{Program Instance} + Switches the type-checking to \Program~(chapter \ref{Program}) + and uses the obligation mechanism to manage missing fields. + +\item {\tt Declare Instance} \comindex{Declare Instance} + In a {\tt Module Type}, this command states that a corresponding + concrete instance should exist in any implementation of this + {\tt Module Type}. This is similar to the distinction between + {\tt Parameter} vs. {\tt Definition}, or between {\tt Declare Module} + and {\tt Module}. + +\end{Variants} + +Besides the {\tt Class} and {\tt Instance} vernacular commands, there +are a few other commands related to type classes. + +\subsection{\tt Existing Instance {\ident}} +\comindex{Existing Instance} +\label{ExistingInstance} + +This commands adds an arbitrary constant whose type ends with an applied +type class to the instance database. It can be used for redeclaring +instances at the end of sections, or declaring structure projections as +instances. This is almost equivalent to {\tt Hint Resolve {\ident} : + typeclass\_instances}. + +\subsection{\tt Context {\binder$_1$ \ldots \binder$_n$}} +\comindex{Context} +\label{Context} + +Declares variables according to the given binding context, which might +use implicit generalization (see \ref{SectionContext}). + +\subsection{\tt Typeclasses Transparent, Opaque {\ident$_1$ \ldots \ident$_n$}} +\comindex{Typeclasses Transparent} +\comindex{Typeclasses Opaque} +\label{TypeclassesTransparency} + +This commands defines the transparency of {\ident$_1$ \ldots \ident$_n$} +during type class resolution. It is useful when some constants prevent some +unifications and make resolution fail. It is also useful to declare +constants which should never be unfolded during proof-search, like +fixpoints or anything which does not look like an abbreviation. This can +additionally speed up proof search as the typeclass map can be indexed +by such rigid constants (see \ref{HintTransparency}). +By default, all constants and local variables are considered transparent. +One should take care not to make opaque any constant that is used to +abbreviate a type, like {\tt relation A := A -> A -> Prop}. + +This is equivalent to {\tt Hint Transparent,Opaque} {\ident} {\tt: typeclass\_instances}. + +\subsection{\tt Typeclasses eauto := [debug] [dfs | bfs] [\emph{depth}]} +\comindex{Typeclasses eauto} +\label{TypeclassesEauto} + +This commands allows to customize the type class resolution tactic, +based on a variant of eauto. The flags semantics are: +\begin{itemize} +\item {\tt debug} In debug mode, the trace of successfully applied + tactics is printed. +\item {\tt dfs, bfs} This sets the search strategy to depth-first search + (the default) or breadth-first search. +\item {\emph{depth}} This sets the depth of the search (the default is 100). +\end{itemize} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "Reference-Manual" +%%% End: |