diff options
Diffstat (limited to 'doc/refman/Classes.tex')
-rw-r--r-- | doc/refman/Classes.tex | 264 |
1 files changed, 261 insertions, 3 deletions
diff --git a/doc/refman/Classes.tex b/doc/refman/Classes.tex index 3a90a59f1..e3ecbb804 100644 --- a/doc/refman/Classes.tex +++ b/doc/refman/Classes.tex @@ -2,6 +2,7 @@ \def\eol{\setlength\parskip{0pt}\par} \def\indent#1{\noindent\kern#1} \def\cst#1{\textsf{#1}} +\def\tele#1{\overrightarrow{#1}} \achapter{\protect{Type Classes}} \aauthor{Matthieu Sozeau} @@ -12,12 +13,12 @@ \end{flushleft} This chapter presents a quick reference of the commands related to type -classes. It is not meant as an introduction to type classes altough it -may become one in the future. For an actual introduction, there is a +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 a mix between the record syntax of \Coq~and the type classes syntax of \Haskell: @@ -32,7 +33,7 @@ record syntax of \Coq~and the type classes syntax of \Haskell: \eol\indent{3.00em}$\cst{f}_m : \phi_m$. \medskip} { - + \medskip \kw{Instance} \classid{Id} $t_1 \cdots t_n$ := \eol\indent{3.00em}$\cst{f}_1 := b_1$ ; @@ -45,6 +46,263 @@ record syntax of \Coq~and the type classes syntax of \Haskell: Reset Initial. \end{coq_eval} +The $\tele{\alpha_i : \tau_i}$ variables are called the \emph{parameters} +of the class and the $\tele{f_k : \phi_k}$ are called the +\emph{methods}. Each class definition gives rise to a corresponding +record declaration and each instance is a regular definition whose 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 Eq (A : Type) := + eq : A -> A -> bool ; + eq_leibniz : forall x y, eq 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 Eq unit := + eq x y := true ; + eq_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 : Eq bool := + eq x y := if x then y else negb y. +\end{coq_example*} + +\begin{coq_example} + Proof. intros x y H. + destruct x ; destruct y ; try 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 neq {A : Type} [ Eq A ] (x y : A) := negb (eq 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{Eq A} is generated and +satisfied by \texttt{[ Eq A ]}. In case no satisfying constraint can be +found, an error is raised: + +\begin{coq_example} + Definition neq' (A : Type) (x y : A) := negb (eq 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 neq' (A : Type) (eqa : Eq A) (x y : A) := negb (eq x y). +\end{coq_example} + +However, the bracketed 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 class arguments and + partialy applied type classes \S \ref{classes:implicitquant} +\item They support implicit quantification on superclasses (see section + \S \ref{classes:superclasses} +\end{itemize} + +\subsection{Implicit quantification} + +Implicit quantification is an automatic elaboration of a statement with +free variables into a closed statement where these variables are +quantified explicitely. Implicit generalization is done only inside +bracketed binders. + +Following the previous example, one can write: +\begin{coq_example} + Definition neq_impl [ eqa : Eq A ] (x y : A) := negb (eq x y). +\end{coq_example} + +Here \texttt{A} is implicitely generalized, and the resulting function +is equivalent to the one above. One must be careful that \emph{all} the +free variables are generalized, which may result in confusing errors in +case of typos. + +\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 [ eqa : Eq A, eqb : Eq B ] => prod_eq : Eq (A * B) := + eq x y := match x, y with + | (la, ra), (lb, rb) => andb (eq la lb) (eq ra rb) + end. +\end{coq_example*} +\begin{coq_eval} +Admitted. +\end{coq_eval} + +These instances are used just as well as lemmas in the instances hint database. + +\asection{Building hierarchies} + +\subsection{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 [ eqa : Eq A ] => Ord := + le : A -> A -> bool. +\end{coq_example} + +This declaration means that any instance of the \texttt{Ord} class must +have an instance of \texttt{Eq}. The parameters of the subclass contains +at least all the parameters of its superclasses in their order of +appearance (here \texttt{A} is the only one). + +Internally, \texttt{Ord} will become a record type with two parameters: +a type \texttt{A} and an object of type \texttt{Eq A}. However, one can +still use it as if it had a single parameter inside class binders: the +generalization of superclasses will be done automatically. +\begin{coq_example} +Definition le_eq [ 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 +explicitely 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 : Eq A, ! Ord eqA ] (x y : A) := + andb (le x y) (neq 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. +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 the 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$}. A optional context of the form {\tt [ C$_1$, \ldots + C$_j$ ] =>} can be put before the name of the class to declare +superclasses. + +\subsection{\tt Instance {\ident} : {Class} {t$_1$ \ldots t$_n$} + := 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. + +A arbitrary context of the form {\tt \binder$_1$ \ldots \binder$_n$ =>} +can be put before the name of the instance to declare a parameterized instance. + +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 Typeclasses unfold {\ident$_1$ \ldots \ident$_n$}} +\comindex{Typeclasses unfold} +\label{TypeclassesUnfold} + +This commands declares {\ident} as an unfoldable constant during type +class resolution. It is useful when some constants prevent some +unifications and make resolution fail. It happens in particular when constants are +used to abbreviate type, like {\tt relation A := A -> A -> Prop}. +This is equivalent to {\tt Hint Unfold {\ident} : 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" |