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
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
|
\def\Program{\textsc{Program}}
\def\Russell{\textsc{Russell}}
\def\PVS{\textsc{PVS}}
\achapter{\Program{}}
\label{Program}
\aauthor{Matthieu Sozeau}
\index{Program}
\begin{flushleft}
\em The status of \Program\ is experimental.
\end{flushleft}
We present here the new \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
(chapter \ref{Extraction}). The goal of \Program~is to program as in a regular
functional programming language whilst using as rich a specification as
desired and proving that the code meets the specification using the whole \Coq{} proof
apparatus. This is done using a technique originating from the
``Predicate subtyping'' mechanism of \PVS \cite{Rushby98}, which generates type-checking
conditions while typing a term constrained to a particular type.
Here we insert existential variables in the term, which must be filled
with proofs to get a complete \Coq\ term. \Program\ replaces the
\Program\ tactic by Catherine Parent \cite{Parent95b} which had a similar goal but is no longer
maintained.
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. We use the same syntax as \Coq\ and permit to use implicit
arguments and the existing coercion mechanism.
Input terms and types are typed in an extended system (\Russell) 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}
The main difference from \Coq\ is that an object in a type $T : \Set$
can be considered as an object of type $\{ x : T~|~P\}$ for any
wellformed $P : \Prop$.
If we go from $T$ to the subset of $T$ verifying property $P$, we must
prove that the object under consideration verifies it. \Russell\ will
generate an obligation for every such coercion. In the other direction,
\Russell\ will automatically insert a projection.
Another distinction is the treatment of pattern-matching. Apart from the
following differences, it is equivalent to the standard {\tt match}
operation (section \ref{Caseexpr}).
\begin{itemize}
\item Generation of equalities. A {\tt match} expression is always
generalized by the corresponding equality. As an example,
the expression:
\begin{coq_example*}
match x with
| 0 => t
| S n => u
end.
\end{coq_example*}
will be first rewrote to:
\begin{coq_example*}
(match x as y return (x = y -> _) with
| 0 => fun H : x = 0 -> t
| S n => fun H : x = S n -> u
end) (refl_equal n).
\end{coq_example*}
This permits to get the proper equalities in the context of proof
obligations inside clauses, without which reasoning is very limited.
\item Coercion. If the object being matched is coercible to an inductive
type, the corresponding coercion will be automatically inserted. This also
works with the previous mechanism.
\end{itemize}
The next two commands are similar to their standard counterparts
Definition (section \ref{Simpl-definitions}) and Fixpoint (section \ref{Fixpoint}) in that
they define constants. However, they may require the user to prove some
goals to construct the final definitions. {\em Note:} every subtac
definition must end with the {\tt Defined} vernacular.
\subsection{\tt Program Definition {\ident} := {\term}.
\comindex{Program Definition}\label{ProgramDefinition}}
This command types the value {\term} in \Russell\ 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}
\subsection{\tt Program Fixpoint {\ident} {\params} {\tt \{order\}} : type := \term
\comindex{Program Fixpoint}
\label{ProgramFixpoint}}
The structural fixpoint operator behaves just like the one of Coq
(section \ref{Fixpoint}), except it may also generate obligations.
\begin{coq_example}
Program Fixpoint div2 (n : nat) : { x : nat | n = 2 * x \/ n = 2 * x + 1 } :=
match n with
| S (S p) => S (div2 p)
| _ => O
end.
\end{coq_example}
Here we have one obligation for each branch (branches for \verb:0: and \verb:(S 0): are
automatically generated by the pattern-matching compilation algorithm):
\begin{coq_example}
Show.
\end{coq_example}
\subsection{\tt Program Lemma {\ident} : type.
\comindex{Program Lemma}
\label{ProgramLemma}}
The \Russell\ language can also be used to type statements of logical
properties. It will currently fail if the traduction to \Coq\
generates obligations though it can be useful to insert automatic coercions.
% \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 8890 2006-06-01 21:33:26Z msozeau $
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "Reference-Manual"
%%% End:
|