aboutsummaryrefslogtreecommitdiff
path: root/doc/refman/Classes.tex
blob: 3ac49269a829cc38903a735ad4e4a1a30b4689ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
\def\Haskell{\textsc{Haskell}\xspace}
\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}
\label{typeclasses}

\begin{flushleft}
  \em The status of Type Classes is (extremelly) 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 a mix between the
record syntax of \Coq~and the type classes syntax of \Haskell:
\def\kw{\texttt}
\def\classid{\texttt}

\begin{center}
\[\begin{array}{l}
\kw{Class}~\classid{Id}~(\alpha_1 : \tau_1) \cdots (\alpha_n : \tau_n) :=\\
\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.
\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 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 unit_Eq : 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:impl-quant})
\item They support implicit quantification on superclasses (\S \ref{classes:superclasses})
\end{itemize}

\subsection{Implicit quantification}
\label{classes:impl-quant}

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 prod_eq [ eqa : Eq A, eqb : Eq B ] : 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}
\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 [ 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"
%%% compile-command: "make -C ../.. -f Makefile.stage3 doc/refman/Reference-Manual.pdf"
%%% End: