summaryrefslogtreecommitdiff
path: root/doc/refman/Program.tex
blob: ed1e6e63212dc665eafeb121d54b4bd5d028a90a (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
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
\def\Program{\textsc{Program}}
\def\Russel{\textsc{Russel}}

\achapter{The \Program{} tactic}
\label{Program}
\aauthor{Matthieu Sozeau}
\index{Program}

\begin{flushleft}
  \em The status of \Program is experimental.
\end{flushleft}

We present here the \Coq\ \Program tactic commands, used to build certified
\Coq programs, elaborating them from their algorithmic skeleton and a
rich specification. It can be sought of as a dual of extraction \ref{Extraction}.
The languages available as input are currently restricted to \Coq's term
language, but may be extended to \ocaml{}, \textsc{Haskell} and others
in the future. Input terms and types are typed in an extended system (\Russel) and
interpreted into \Coq\ terms. The interpretation process may produce
some proof obligations which need to be resolved to create the final term.

\asection{Elaborating programs}
\comindex{Program Fixpoint}

The next two commands are similar to they standard counterparts
\ref{Simpl-definitions} and \ref{Fixpoint} in that
they define constants. However, they may require the user to prove some
goals to construct the final definitions.

\section{\tt Program Definition {\ident} := {\term}.
  \comindex{Program Definition}\label{ProgramDefinition}}

This command types the value {\term} in \Russel and generate subgoals
corresponding to proof obligations. Once solved, it binds the final
\Coq\ term to the name {\ident} in the environment.

\begin{ErrMsgs}
\item \errindex{{\ident} already exists}
\end{ErrMsgs}

\begin{Variants}
\item {\tt Program Definition {\ident} {\tt :}{\term$_1$} :=
    {\term$_2$}.}\\
  It interprets the type {\term$_1$}, potentially generating proof
  obligations to be resolved. Once done with them, we have a \Coq\ type
  {\term$_1'$}. It then checks that the type of the interpretation of
  {\term$_2$} is coercible to {\term$_1'$}, and registers {\ident} as
  being of type {\term$_1'$} once the set of obligations generated
  during the interpretation of {\term$_2$} and the aforementioned
  coercion derivation are solved.
\item {\tt Program Definition {\ident} {\binder$_1$}\ldots{\binder$_n$}
       {\tt :}\term$_1$ {\tt :=} {\term$_2$}.}\\
  This is equivalent to \\
   {\tt Program Definition\,{\ident}\,{\tt :\,forall}\,%
       {\binder$_1$}\ldots{\binder$_n$}{\tt ,}\,\term$_1$\,{\tt :=}}\,%
       {\tt fun}\,{\binder$_1$}\ldots{\binder$_n$}\,{\tt =>}\,{\term$_2$}\,%
       {\tt .}
\end{Variants}

\begin{ErrMsgs}
\item \errindex{In environment {\dots} the term: {\term$_2$} does not have type
    {\term$_1$}}.\\
    \texttt{Actually, it has type {\term$_3$}}.
\end{ErrMsgs}

\SeeAlso Sections \ref{Opaque}, \ref{Transparent}, \ref{unfold}

\section{\tt Program Fixpoint {\ident} {\params} {\tt \{order\}} : type$_0$ := \term$_0$ 
  \comindex{Program Fixpoint}
  \label{ProgramFixpoint}}

This command allows to define objects using a fixed point
construction. The meaning of this declaration is to define {\it ident}
a recursive function with arguments specified by
{\binder$_1$}\ldots{\binder$_n$} such that {\it ident} applied to
arguments corresponding to these binders has type \type$_0$, and is
equivalent to the expression \term$_0$. The type of the {\ident} is
consequently {\tt forall {\params} {\tt,} \type$_0$}
and the value is equivalent to {\tt fun {\params} {\tt =>} \term$_0$}.

There are two ways to define fixpoints with \Program{}, structural and
well-founded recursion.

\subsection{\tt Program Fixpoint {\ident} {\params} {\tt \{struct}
  \ident$_0$ {\tt \}} : type$_0$ := \term$_0$  
  \comindex{Program Fixpoint Struct}
  \label{ProgramFixpointStruct}}

To be accepted, a structural {\tt Fixpoint} definition has to satisfy some
syntactical constraints on a special argument called the decreasing
argument. They are needed to ensure that the {\tt Fixpoint} definition
always terminates. The point of the {\tt \{struct \ident {\tt \}}}
annotation is to let the user tell the system which argument decreases
along the recursive calls. This annotation may be left implicit for
fixpoints with one argument. For instance, one can define the identity
function on naturals as :

\begin{coq_example}
Program Fixpoint id (n : nat) : { x : nat | x = n } :=
  match n with
  | O => O
  | S p => S (id p)
  end.
\end{coq_example}

The {\tt match} operator matches a value (here \verb:n:) with the
various constructors of its (inductive) type. The remaining arguments
give the respective values to be returned, as functions of the
parameters of the corresponding constructor. Thus here when \verb:n:
equals \verb:O: we return \verb:0:, and when \verb:n: equals 
\verb:(S p): we return \verb:(S (id p)):.

The {\tt match} operator is formally described
in detail in Section~\ref{Caseexpr}.  The system recognizes that in
the inductive call {\tt (id p)} the argument actually
decreases because it is a {\em pattern variable} coming from {\tt match
  n with}.

Here again, proof obligations may be generated. In our example, we would
have one for each branch:
\begin{coq_example}
Show.
\end{coq_example}

% \subsection{\tt Program Fixpoint {\ident} {(\ident_$_0$ : \type_$_0$)
%     \cdots (\ident_$_n$ : \type_$_n$)} {\tt \{wf}
%   \ident$_i$ \term_{wf} {\tt \}} : type$_t$ := \term$_0$
%   \comindex{Program Fixpoint Wf}
%   \label{ProgramFixpointWf}}

% To be accepted, a well-founded {\tt Fixpoint} definition has to satisfy some
% logical constraints on the decreasing argument. 
% They are needed to ensure that the {\tt Fixpoint} definition
% always terminates. The point of the {\tt \{wf \ident \term {\tt \}}}
% annotation is to let the user tell the system which argument decreases
% in which well-founded relation along the recursive calls. 
% The term \term$_0$ will be typed in a different context than usual,
% The typing problem will in fact be reduced to: 

% % \begin{center}
% %   {\tt forall} {\params} {\ident : (\ident$_0$ : type$_0$) \cdots
% %     \{ \ident$_i'$ : \type$_i$ | \term_{wf} \ident$_i'$ \ident$_i$ \}
% %     \cdots (\ident$_n$ : type$_n$), type$_t$} : type$_t$ := \term$_0$
% % \end{center}

% \begin{coq_example}
% Program Fixpoint id (n : nat) : { x : nat | x = n } :=
%   match n with
%   | O => O
%   | S p => S (id p)
%   end
% \end{coq_example}

% The {\tt match} operator matches a value (here \verb:n:) with the
% various constructors of its (inductive) type. The remaining arguments
% give the respective values to be returned, as functions of the
% parameters of the corresponding constructor. Thus here when \verb:n:
% equals \verb:O: we return \verb:0:, and when \verb:n: equals 
% \verb:(S p): we return \verb:(S (id p)):.

% The {\tt match} operator is formally described
% in detail in Section~\ref{Caseexpr}.  The system recognizes that in
% the inductive call {\tt (id p)} the argument actually
% decreases because it is a {\em pattern variable} coming from {\tt match
%   n with}.

% Here again, proof obligations may be generated. In our example, we would
% have one for each branch:
% \begin{coq_example}
% Show.
% \end{coq_example}
% \begin{coq_eval}
% Abort.
% \end{coq_eval}




% \asubsection{A detailed example: Euclidean division}

% The file {\tt Euclid} contains the proof of Euclidean division
% (theorem {\tt eucl\_dev}). The natural numbers defined in the example
% files are unary integers defined by two constructors $O$ and $S$:
% \begin{coq_example*}
% Inductive nat : Set :=
%   | O : nat
%   | S : nat -> nat.
% \end{coq_example*}

% This module contains a theorem {\tt eucl\_dev}, and its extracted term
% is of type 
% \begin{verbatim}
% forall b:nat, b > 0 -> forall a:nat, diveucl a b
% \end{verbatim}
% where {\tt diveucl} is a type for the pair of the quotient and the modulo.
% We can now extract this program to \ocaml:

% \begin{coq_eval}
% Reset Initial.
% \end{coq_eval}
% \begin{coq_example}
% Require Import Euclid.
% Extraction Inline Wf_nat.gt_wf_rec Wf_nat.lt_wf_rec.
% Recursive Extraction  eucl_dev.
% \end{coq_example}

% The inlining of {\tt gt\_wf\_rec} and {\tt lt\_wf\_rec} is not
% mandatory. It only enhances readability of extracted code. 
% You can then copy-paste the output to a file {\tt euclid.ml} or let 
% \Coq\ do it for you with the following command: 

% \begin{coq_example}
% Extraction "euclid" eucl_dev.
% \end{coq_example}

% Let us play the resulting program:

% \begin{verbatim}
% # #use "euclid.ml";;
% type sumbool = Left | Right
% type nat = O | S of nat
% type diveucl = Divex of nat * nat
% val minus : nat -> nat -> nat = <fun>
% val le_lt_dec : nat -> nat -> sumbool = <fun>
% val le_gt_dec : nat -> nat -> sumbool = <fun>
% val eucl_dev : nat -> nat -> diveucl = <fun>
% # eucl_dev (S (S O)) (S (S (S (S (S O)))));;
% - : diveucl = Divex (S (S O), S O)
% \end{verbatim}
% It is easier to test on \ocaml\ integers:
% \begin{verbatim}
% # let rec i2n = function 0 -> O | n -> S (i2n (n-1));;
% val i2n : int -> nat = <fun>
% # let rec n2i = function O -> 0 | S p -> 1+(n2i p);;
% val n2i : nat -> int = <fun>
% # let div a b = 
%      let Divex (q,r) = eucl_dev (i2n b) (i2n a) in (n2i q, n2i r);;
% div : int -> int -> int * int = <fun>
% # div 173 15;;
% - : int * int = 11, 8
% \end{verbatim}

% \asubsection{Another detailed example: Heapsort}

% The file {\tt Heap.v}
% contains the proof of an efficient list sorting algorithm described by
% Bjerner. Is is an adaptation of the well-known {\em heapsort}
% algorithm to functional languages. The main function is {\tt
% treesort}, whose type is shown below: 


% \begin{coq_eval}
% Reset Initial.
% Require Import Relation_Definitions.
% Require Import List.
% Require Import Sorting.
% Require Import Permutation.
% \end{coq_eval}
% \begin{coq_example}
% Require Import Heap.
% Check treesort.
% \end{coq_example}

% Let's now extract this function: 

% \begin{coq_example}
% Extraction Inline sort_rec is_heap_rec.
% Extraction NoInline list_to_heap.
% Extraction "heapsort" treesort.
% \end{coq_example}

% One more time, the {\tt Extraction Inline} and {\tt NoInline}
% directives are cosmetic. Without it, everything goes right, 
% but the output is less readable.
% Here is the produced file {\tt heapsort.ml}: 

% \begin{verbatim}
% type nat =
%   | O
%   | S of nat

% type 'a sig2 =
%   'a
%   (* singleton inductive, whose constructor was exist2 *)
  
% type sumbool =
%   | Left
%   | Right

% type 'a list =
%   | Nil
%   | Cons of 'a * 'a list

% type 'a multiset =
%   'a -> nat
%   (* singleton inductive, whose constructor was Bag *)
  
% type 'a merge_lem =
%   'a list
%   (* singleton inductive, whose constructor was merge_exist *)
  
% (** val merge : ('a1 -> 'a1 -> sumbool) -> ('a1 -> 'a1 -> sumbool) ->
%                 'a1 list -> 'a1 list -> 'a1 merge_lem **)

% let rec merge leA_dec eqA_dec l1 l2 =
%   match l1 with
%     | Nil -> l2
%     | Cons (a, l) ->
%         let rec f = function
%           | Nil -> Cons (a, l)
%           | Cons (a0, l3) ->
%               (match leA_dec a a0 with
%                  | Left -> Cons (a,
%                      (merge leA_dec eqA_dec l (Cons (a0, l3))))
%                  | Right -> Cons (a0, (f l3)))
%         in f l2

% type 'a tree =
%   | Tree_Leaf
%   | Tree_Node of 'a * 'a tree * 'a tree

% type 'a insert_spec =
%   'a tree
%   (* singleton inductive, whose constructor was insert_exist *)
  
% (** val insert : ('a1 -> 'a1 -> sumbool) -> ('a1 -> 'a1 -> sumbool) ->
%                  'a1 tree -> 'a1 -> 'a1 insert_spec **)

% let rec insert leA_dec eqA_dec t a =
%   match t with
%     | Tree_Leaf -> Tree_Node (a, Tree_Leaf, Tree_Leaf)
%     | Tree_Node (a0, t0, t1) ->
%         let h3 = fun x -> insert leA_dec eqA_dec t0 x in
%         (match leA_dec a0 a with
%            | Left -> Tree_Node (a0, t1, (h3 a))
%            | Right -> Tree_Node (a, t1, (h3 a0)))

% type 'a build_heap =
%   'a tree
%   (* singleton inductive, whose constructor was heap_exist *)
  
% (** val list_to_heap : ('a1 -> 'a1 -> sumbool) -> ('a1 -> 'a1 ->
%                        sumbool) -> 'a1 list -> 'a1 build_heap **)

% let rec list_to_heap leA_dec eqA_dec = function
%   | Nil -> Tree_Leaf
%   | Cons (a, l0) ->
%       insert leA_dec eqA_dec (list_to_heap leA_dec eqA_dec l0) a

% type 'a flat_spec =
%   'a list
%   (* singleton inductive, whose constructor was flat_exist *)
  
% (** val heap_to_list : ('a1 -> 'a1 -> sumbool) -> ('a1 -> 'a1 ->
%                        sumbool) -> 'a1 tree -> 'a1 flat_spec **)

% let rec heap_to_list leA_dec eqA_dec = function
%   | Tree_Leaf -> Nil
%   | Tree_Node (a, t0, t1) -> Cons (a,
%       (merge leA_dec eqA_dec (heap_to_list leA_dec eqA_dec t0)
%         (heap_to_list leA_dec eqA_dec t1)))

% (** val treesort : ('a1 -> 'a1 -> sumbool) -> ('a1 -> 'a1 -> sumbool)
%                    -> 'a1 list -> 'a1 list sig2 **)

% let treesort leA_dec eqA_dec l =
%   heap_to_list leA_dec eqA_dec (list_to_heap leA_dec eqA_dec l)

% \end{verbatim}

% Let's test it: 
% % Format.set_margin 72;;
% \begin{verbatim}
% # #use "heapsort.ml";;
% type sumbool = Left | Right
% type nat = O | S of nat
% type 'a tree = Tree_Leaf | Tree_Node of 'a * 'a tree * 'a tree
% type 'a list = Nil | Cons of 'a * 'a list
% val merge : 
%   ('a -> 'a -> sumbool) -> 'b -> 'a list -> 'a list -> 'a list = <fun>
% val heap_to_list : 
%   ('a -> 'a -> sumbool) -> 'b -> 'a tree -> 'a list = <fun>
% val insert : 
%   ('a -> 'a -> sumbool) -> 'b -> 'a tree -> 'a -> 'a tree = <fun>
% val list_to_heap : 
%   ('a -> 'a -> sumbool) -> 'b -> 'a list -> 'a tree = <fun>
% val treesort : 
%   ('a -> 'a -> sumbool) -> 'b -> 'a list -> 'a list = <fun>
% \end{verbatim}

% One can remark that the argument of {\tt treesort} corresponding to 
% {\tt eqAdec} is never used in the informative part of the terms, 
% only in the logical parts. So the extracted {\tt treesort} never use
% it, hence this {\tt 'b} argument. We will use {\tt ()} for this
% argument. Only remains the {\tt leAdec}
% argument (of type {\tt 'a -> 'a -> sumbool}) to really provide.

% \begin{verbatim}
% # let leAdec x y = if x <= y then Left else Right;;
% val leAdec : 'a -> 'a -> sumbool = <fun>
% # let rec listn = function 0 -> Nil
%                          | n -> Cons(Random.int 10000,listn (n-1));;
% val listn : int -> int list = <fun>
% # treesort leAdec () (listn 9);;
% - : int list = Cons (160, Cons (883, Cons (1874, Cons (3275, Cons 
%   (5392, Cons (7320, Cons (8512, Cons (9632, Cons (9876, Nil)))))))))
% \end{verbatim}

% Some tests on longer lists (10000 elements) show that the program is
% quite efficient for Caml code.


% \asubsection{The Standard Library} 

% As a test, we propose an automatic extraction of the 
% Standard Library of \Coq. In particular, we will find back the
% two previous examples, {\tt Euclid} and {\tt Heapsort}. 
% Go to directory {\tt contrib/extraction/test} of the sources of \Coq,
% and run commands: 
% \begin{verbatim}
% make tree; make
% \end{verbatim}
% This will extract all Standard Library files and compile them. 
% It is done via many {\tt Extraction Module}, with some customization
% (see subdirectory {\tt custom}).

% %The result of this extraction of the Standard Library can be browsed
% %at URL 
% %\begin{flushleft}
% %\url{http://www.lri.fr/~letouzey/extraction}.
% %\end{flushleft}
                                
% %Reals theory is normally not extracted, since it is an axiomatic 
% %development. We propose nonetheless a dummy realization of those
% %axioms, to test, run: \\
% %
% %\mbox{\tt make reals}\\

% This test works also with Haskell. In the same directory, run:
% \begin{verbatim}
% make tree; make -f Makefile.haskell
% \end{verbatim}
% The haskell compiler currently used is {\tt hbc}.  Any other should
% also work, just adapt the {\tt Makefile.haskell}. In particular {\tt
%  ghc} is known to work.

% \asubsection{Extraction's horror museum}

% Some pathological examples of extraction are grouped in the file
% \begin{verbatim}
% contrib/extraction/test_extraction.v
% \end{verbatim}
% of the sources of \Coq.

% \asubsection{Users' Contributions}

%  Several of the \Coq\ Users' Contributions use extraction to produce 
%  certified programs. In particular the following ones have an automatic 
%  extraction test (just run {\tt make} in those directories): 

%  \begin{itemize}
%  \item Bordeaux/Additions
%  \item Bordeaux/EXCEPTIONS
%  \item Bordeaux/SearchTrees
%  \item Dyade/BDDS
%  \item Lannion
%  \item Lyon/CIRCUITS
%  \item Lyon/FIRING-SQUAD
%  \item Marseille/CIRCUITS
%  \item Muenchen/Higman
%  \item Nancy/FOUnify
%  \item Rocq/ARITH/Chinese
%  \item Rocq/COC
%  \item Rocq/GRAPHS
%  \item Rocq/HIGMAN
%  \item Sophia-Antipolis/Stalmarck
%  \item Suresnes/BDD
%  \end{itemize}

%  Lannion, Rocq/HIGMAN and Lyon/CIRCUITS are a bit particular. They are 
%  the only examples of developments where {\tt Obj.magic} are needed.
%  This is probably due to an heavy use of impredicativity.
%  After compilation those two examples run nonetheless,
%  thanks to the correction of the extraction~\cite{Let02}. 

% $Id: Program.tex 8688 2006-04-07 15:08:12Z msozeau $ 

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "Reference-Manual"
%%% End: