aboutsummaryrefslogtreecommitdiffhomepage
path: root/doc/Extraction.tex
diff options
context:
space:
mode:
authorGravatar filliatr <filliatr@85f007b7-540e-0410-9357-904b9bb8a0f7>2000-12-12 22:36:15 +0000
committerGravatar filliatr <filliatr@85f007b7-540e-0410-9357-904b9bb8a0f7>2000-12-12 22:36:15 +0000
commitb6018c78b25da14d4f44cf10de692f968cba1e98 (patch)
treec152b9761b70cbc554efdc2f05f3a995444ed259 /doc/Extraction.tex
parent88e2679b89a32189673b808acfe3d6181a38c000 (diff)
Initial revision
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@8143 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'doc/Extraction.tex')
-rwxr-xr-xdoc/Extraction.tex557
1 files changed, 557 insertions, 0 deletions
diff --git a/doc/Extraction.tex b/doc/Extraction.tex
new file mode 100755
index 000000000..cb9949d97
--- /dev/null
+++ b/doc/Extraction.tex
@@ -0,0 +1,557 @@
+\achapter{Execution of extracted programs in Caml and Haskell}
+\label{CamlHaskellExtraction}
+\aauthor{Benjamin Werner and Jean-Christophe Filliātre}
+\index{Extraction}
+
+It is possible to use \Coq\ to build certified and relatively
+efficient programs, extracting them from the proofs of their
+specifications. The extracted objects are terms of \FW, and can be
+obtained at the \Coq\ toplevel with the command {\tt Extraction}
+(see \ref{Extraction}).
+
+We present here a \Coq\ module, {\tt Extraction}, which translates the
+extracted terms to ML dialects, namely Caml Light, Objective Caml and
+Haskell. In the following, we will not refer to a particular dialect
+when possible and ``ML'' will be used to refer to any of the target
+dialects.
+
+One builds effective programs in an \FW\ toplevel (actually the \Coq\
+toplevel) which contains the extracted objects and in which one can
+import ML objects. Indeed, in order to instantiate and realize \Coq\
+type and term variables, it is possible to import ML
+objects in the \FW\ toplevel, as inductive types or axioms.
+
+\Rem
+The current mechanism of extraction of effective programs
+from \Coq\ proofs slightly differs from the one in the versions of
+\Coq\ anterior to the version V5.8. In these versions, there were an
+explicit toplevel for the language {\sf Fml}. Moreover, it was not
+possible to import ML objects in this {\sf Fml} toplevel.
+
+
+%\section{Extraction facilities}
+%
+%(* TO DO *)
+%
+
+\medskip
+In the first part of this document we describe the commands of the
+{\tt Extraction} module, and we give some examples in the second part.
+
+
+\asection{The {\tt Extraction} module}
+\label{Extraction}
+
+This section explains how to import ML objects, to realize axioms and
+finally to generate ML code from the extracted programs of \FW.
+
+These features do not belong to the core system, and appear as an
+independent module called {\tt Extraction.v} (which is compiled during the
+installation of the system). So the first thing to do is to load this
+module:
+
+\begin{coq_example*}
+Require Extraction.
+\end{coq_example*}
+
+\asubsection{Generating executable ML code}
+\comindex{Write Caml File}
+\comindex{Write CamlLight File}
+\comindex{Write Haskell File}
+The \Coq\ commands to generate ML code are:
+\begin{center}\begin{tabular}{ll}
+ {\tt Write Caml File "\str" [ \ident$_1$ \dots\ \ident$_n$ ]
+ {\it options}.}
+ & ({\em for Objective Caml\/}) \\
+ {\tt Write CamlLight File "\str" [ \ident$_1$ \dots\ \ident$_n$ ]
+ {\it options}.} & \\
+ {\tt Write Haskell File "\str" [ \ident$_1$ \dots\ \ident$_n$ ]
+ {\it options}.} & \\
+\end{tabular}\end{center}
+where \str\ is the name given to the file to be produced (the suffix
+{\tt .ml} is added if necessary), and \ident$_1$ \dots\ \ident$_n$ the
+names of the constants to be extracted. This list does not need to be
+exhaustive: it is automatically completed into a complete and minimal
+environment. Remaining axioms are translated into exceptions, and a
+warning is printed in that case. In particular, this will be the case
+for {\tt False\_rec}. (We will see below how to realize axioms).
+
+\paragraph{Optimizations.}
+Since Caml Light and Objective Caml are strict languages, the extracted
+code has to be optimized in order to be efficient (for instance, when
+using induction principles we do not want to compute all the recursive
+calls but only the needed ones). So an optimization routine will be
+called each time the user want to generate Caml programs. Essentially,
+it performs constants expansions and reductions. Therefore some
+constants will not appear in the resulting Caml program (A warning is
+printed for each such constant). To avoid this, just put the constant
+name in the previous list \ident$_1$ \dots\ \ident$_n$ and it will not
+be expanded. Moreover, three options allow the user to control the
+expansion strategy :
+\begin{description}
+ \item[\texttt{noopt}] : specifies not to do any optimization.
+ \item[\texttt{exact}] : specifies to extract exactly the given
+ objects (no recursivity).
+ \item[\texttt{expand [ \ident$_1$ \dots\ \ident$_n$ ]}] :
+ forces the expansion of the constants \ident$_1$ \dots\ \ident$_n$
+ (when it is possible).
+\end{description}
+
+
+\asubsection{Realizing axioms}
+\comindex{Link}
+
+It is possible to assume some axioms while developing a proof. Since
+these axioms can be any kind of proposition or object type, they may
+perfectly well have some computational content. But a program must be
+a closed term, and of course the system cannot guess the program which
+realizes an axiom. Therefore, it is possible to tell the system
+what program (an \FW\ term actually) corresponds to a given \Coq\
+axiom. The command is {\tt Link} and the syntax:
+$$\mbox{\tt Link \ident\ := Fwterm.}$$
+where \ident\ is the name of the axiom to realize and Fwterm\ the
+term which realizes it. The system checks that this term has the same
+type as the axiom \ident, and returns an error if not. This command
+attaches a body to an axiom, and can be seen as a transformation of an
+axiom into a constant.
+
+These semantical attachments have to be done {\em before} generating
+the ML code. All type variables must be realized, and term variables
+which are not realized will be translated into exceptions.
+
+\Example Let us illustrate this feature on a small
+example. Assume that you have a type variable {\tt A} of type \Set:
+
+\begin{coq_example*}
+Parameter A : Set.
+\end{coq_example*}
+
+and that your specification proof assumes that there is an order
+relation {\em inf} over that type (which has no computational
+content), and that this relation is total and decidable:
+
+\begin{coq_example*}
+Parameter inf : A -> A -> Prop.
+Axiom inf_total : (x,y:A) {(inf x y)}+{(inf y x)}.
+\end{coq_example*}
+
+Now suppose that we want to use this specification proof on natural
+numbers; this means {\tt A} has to be instantiated by {\tt nat}
+and the axiom {\tt inf\_total} will be realized, for instance, using the
+order relation {\tt le} on that type and the decidability lemma
+{\tt le\_lt\_dec}. Here is how to proceed:
+
+\begin{coq_example*}
+Require Compare_dec.
+\end{coq_example*}
+\begin{coq_example}
+Link A := nat.
+Link inf_total := le_lt_dec.
+\end{coq_example}
+
+\Warning There is no rollback on the command {\tt Link}, that
+is the semantical attachments are not forgotten when doing a {\tt Reset},
+or a {\tt Restore State} command. This will be corrected in a later
+version.
+
+\asubsection{Importing ML objects}
+In order to realize axioms and to instantiate programs on real data
+types, like {\tt int}, {\tt string}, \dots\ or more complicated data
+structures, one want to import existing ML objects in the \FW\
+environment. The system provides such features, through the commands
+{\tt ML Import Constant} and {\tt ML Import Inductive}.
+The first one imports an ML
+object as a new axiom and the second one adds a new inductive
+definition corresponding to an ML inductive type.
+
+\paragraph{Warning.}
+In the case of Caml dialects, the system would be able to check the
+correctness of the imported objects by looking into the interfaces
+files of Caml modules ({\tt .mli} files), but this feature is not yet
+implemented. So one must be careful when declaring the types of the
+imported objects.
+
+\paragraph{Caml names.}
+When referencing a Caml object, you can use strings instead of
+identifiers. Therefore you can use the double
+underscore notation \verb!module__name! (Caml Light objects)
+or the dot notation \verb!module.name! (Objective Caml objects)
+to precise the module in which lies the object.
+
+
+\asubsection{Importing inductive types}
+\comindex{ML Import Inductive}
+
+The \Coq\ command to import an ML inductive type is:
+$$\mbox{\tt ML Import Inductive \ident\ [\ident$_1$ \dots\ \ident$_n$] == %
+{\em <Inductive Definition>}.}$$
+where \ident\ is the name of the ML type, \ident$_1$ \dots\
+\ident$_n$ the name of its constructors, and {\tt\em<Inductive
+ Definition>} the corresponding \Coq\ inductive definition
+(see \ref{Inductive} in the Reference Manual for the syntax of
+inductive definitions).
+
+This command inserts the {\tt\em<Inductive Definition>} in the \FW\
+environment, without elimination principles. From that moment, it is
+possible to use that type like any other \FW\ object, and in
+particular to use it to realize axioms. The names \ident\ \ident$_1$
+\dots\ \ident$_n$ may be different from the names given in the
+inductive definition, in order to avoid clash with previous
+constants, and are restored when generating the ML code.
+
+\noindent One can also import mutual inductive types with the command:
+$$\begin{array}{rl}
+ \mbox{\tt ML Import Inductive} &
+ \mbox{\tt\ident$_1$ [\ident$^1_1$ \dots\ \ident$^1_{n_1}$]} \\
+ & \dots \\
+ & \mbox{\tt\ident$_k$ [\ident$^k_1$ \dots\ \ident$^k_{n_k}$]} \\
+ & \qquad \mbox{\tt== {\em<Mutual Inductive Definition>}.}
+ \end{array}$$ %$$
+
+\begin{Examples}
+\item Let us show for instance how to import the
+ type {\tt bool} of Caml Light booleans:
+
+\begin{coq_example}
+ML Import Inductive bool [ true false ] ==
+ Inductive BOOL : Set := TRUE : BOOL
+ | FALSE : BOOL.
+\end{coq_example}
+
+Here we changed the names because the type {\tt bool} is already
+defined in the initial state of \Coq.
+
+ \item Assuming that one defined the mutual inductive types {\tt
+tree} and {\tt forest} in a Caml Light module, one can import them
+with the command:
+
+\begin{coq_example}
+ML Import Inductive tree [node] forest [empty cons] ==
+ Mutual [A:Set] Inductive
+ tree : Set := node : A -> (forest A) -> (tree A)
+ with
+ forest : Set := empty : (forest A)
+ | cons : (tree A) -> (forest A) -> (forest A).
+\end{coq_example}
+
+ \item One can import the polymorphic type of Caml Light lists with
+the command:
+\begin{coq_example}
+ML Import Inductive list [nil cons] ==
+ Inductive list [A:Set] : Set := nil : (list A)
+ | cons : A->(list A)->(list A).
+\end{coq_example}
+
+\Rem One would have to re-define {\tt nil} and {\tt cons} at
+the top of its program because these constructors have no name in Caml Light.
+\end{Examples}
+
+\asubsection{Importing terms and abstract types}
+\comindex{ML Import Constant}
+
+The other command to import an ML object is:
+$$\mbox{\tt ML Import Constant \ident$_{ML}$\ == \ident\ : Fwterm.}$$
+where \ident$_{ML}$\ is the name of the ML object and Fwterm\ its type in
+\FW. This command defines an axiom in \FW\ of name \ident\ and type
+Fwterm.
+
+\Example To import the type {\tt int} of Caml Light
+integers, and the $<$ binary relation on this type, just do
+\begin{coq_example}
+ML Import Constant int == int : Set.
+ML Import Constant lt_int == lt_int : int -> int -> BOOL.
+\end{coq_example}
+assuming that the Caml Light type {\tt bool} is already imported (with the
+name {\tt BOOL}, as above).
+
+
+\asubsection{Direct use of ML\ objects}
+\comindex{Extract Constant}
+\comindex{Extract Inductive}
+
+Sometimes the user do not want to extract \Coq\ objects to new ML code
+but wants to use already existing ML objects. For instance, it is the
+case for the booleans, which already exist in ML: the user do not want
+to extract the \Coq\ inductive type \texttt{bool} to a new type for
+booleans, but wants to use the primitive boolean of ML.
+
+The command \texttt{Extract} fulfills this requirement.
+It allows the user to declare constant and inductive types which will not be
+extracted but replaced by ML objects. The syntax is the following
+$$
+\begin{tabular}{l}
+ \mbox{\tt Extract Constant \ident\ => \ident'.} \\
+ \mbox{\tt Extract Inductive \ident\
+ => \ident' [ \ident'$_1$ \dots \ident'$_n$ ].}
+\end{tabular}
+$$ %$$
+where \ident\/ is the name of the \Coq\ object and the prime identifiers
+the name of the corresponding ML objects (the names between brackets
+are the names of the constructors).
+Mutually recursive types are declared one by one, in any order.
+
+\Example
+Typical examples are the following:
+\begin{coq_example}
+Extract Inductive unit => unit [ "()" ].
+Extract Inductive bool => bool [ true false ].
+Extract Inductive sumbool => bool [ true false ].
+\end{coq_example}
+
+
+\asubsection{Differences between \Coq\ and ML type systems}
+
+\subsubsection{ML types that are not \FW\ types}
+
+Some ML recursive types have no counterpart in the type system of
+\Coq, like types using the record construction, or non positive types
+like
+\begin{verbatim}
+# type T = C of T->T;;
+\end{verbatim}
+In that case, you cannot import those types as inductive types, and
+the only way to do is to import them as abstract types (with {\tt ML
+Import}) together with the corresponding building and de-structuring
+functions (still with {\tt ML Import Constant}).
+
+
+\subsubsection{Programs that are not ML-typable}
+
+On the contrary, some extracted programs in \FW\ are not typable in
+ML. There are in fact two cases which can be problematic:
+\begin{itemize}
+ \item If some part of the program is {\em very} polymorphic, there
+ may be no ML type for it. In that case the extraction to ML works
+ all right but the generated code may be refused by the ML
+ type-checker. A very well known example is the {\em distr-pair}
+ function:
+$$\mbox{\tt
+Definition dp := [A,B:Set][x:A][y:B][f:(C:Set)C->C](f A x,f B y).
+}$$
+In Caml Light, for instance, the extracted term is
+\verb!let dp x y f = pair((f x),(f y))! and has type
+$$\mbox{\tt
+dp : 'a -> 'a -> ('a -> 'b) -> ('b,'b) prod
+}$$
+which is not its original type, but a restriction.
+
+ \item Some definitions of \FW\ may have no counterpart in ML. This
+ happens when there is a quantification over types inside the type
+ of a constructor; for example:
+$$\mbox{\tt
+Inductive anything : Set := dummy : (A:Set)A->anything.
+}$$
+which corresponds to the definition of ML dynamics.
+\end{itemize}
+
+The first case is not too problematic: it is still possible to run the
+programs by switching off the type-checker during compilation. Unless
+you misused the semantical attachment facilities you should never get
+any message like ``segmentation fault'' for which the extracted code
+would be to blame. To switch off the Caml type-checker, use the
+function {\tt obj\_\_magic} which gives the type {\tt 'a} to any
+object; but this implies changing a little the extracted code by hand.
+
+The second case is fatal. If some inductive type cannot be translated
+to ML, one has to change the proof (or possibly to ``cheat'' by
+some low-level manipulations we would not describe here).
+
+We have to say, though, that in most ``realistic'' programs, these
+problems do not occur. For example all the programs of the library are
+accepted by Caml type-checker except {\tt Higman.v}\footnote{Should
+ you obtain a not ML-typable program out of a self developed example,
+ we would be interested in seeing it; so please mail us the example at
+ {\em coq@pauillac.inria.fr}}.
+
+
+\asection{Some examples}
+
+We present here few examples of extractions, taken from the {\tt
+theories} library of \Coq\ (into the {\tt PROGRAMS} directory). We
+choose Caml Light as target language, but all can be done in the other
+dialects with slight modifications.
+
+
+\asubsection{Euclidean division}
+
+The file {\tt Euclid\_prog} 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*}
+
+To use the proof, we begin by loading the module {\tt Extraction} and the
+file into the \Coq\ environment:
+
+\begin{coq_eval}
+Reset Initial.
+AddPath "../theories/DEMOS/PROGRAMS".
+\end{coq_eval}
+\begin{coq_example*}
+Require Extraction.
+Require Euclid_prog.
+\end{coq_example*}
+
+This module contains a theorem {\tt eucl\_dev}, and its extracted term
+is of type {\tt (b:nat)(a:nat) (di\-veucl a b)}, where {\tt diveucl} is a
+type for the pair of the quotient and the modulo.
+We can now extract this program to Caml Light:
+
+\begin{coq_example}
+Write CamlLight File "euclid" [ eucl_dev ].
+\end{coq_example}
+
+This produces a file {\tt euclid.ml} containing all the necessary
+definitions until {\tt let eucl\_dev = ..}. Let us play the resulting program:
+
+\begin{verbatim}
+# include "euclid";;
+# 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 Caml Light integers:
+\begin{verbatim}
+# let rec nat_of = function 0 -> O
+ | n -> S (nat_of (pred n));;
+# let rec int_of = function O -> 0
+ | S p -> succ (int_of p);;
+# let div a b = match eucl_dev (nat_of b) (nat_of a) with
+ divex(q,r) -> (int_of q, int_of r);;
+div : int -> int -> int * int = <fun>
+# div 173 15;;
+- : int * int = 11, 8
+\end{verbatim}
+
+\asubsection{Heapsort}
+
+Let us see a more complicated example. The file {\tt Heap\_prog.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. We first load the files:
+
+\begin{coq_eval}
+Reset Initial.
+\end{coq_eval}
+\begin{coq_example*}
+Require Extraction.
+Require Heap_prog.
+\end{coq_example*}
+
+As we saw it above we have to instantiate or realize by hand some of
+the \Coq\ variables, which are in this case the type of the elements
+to sort ({\tt List\_Dom}, defined in {\tt List.v}) and the
+decidability of the order relation ({\tt inf\_total}). We proceed as
+in section \ref{Extraction}:
+
+\begin{coq_example}
+ML Import Constant int == int : Set.
+Link List_Dom := int.
+ML Import Inductive bool [ true false ] ==
+ Inductive BOOL : Set := TRUE : BOOL
+ | FALSE : BOOL.
+ML Import Constant lt_int == lt_int : int->int->BOOL.
+Link inf_total :=
+ [x,y:int]Cases (lt_int x y) of
+ TRUE => left
+ | FALSE => right
+ end.
+\end{coq_example}
+
+Then we extract the Caml Light program
+
+\begin{coq_example}
+Write CamlLight File "heapsort" [ heapsort ].
+\end{coq_example}
+and test it
+\begin{verbatim}
+
+# include "heapsort";;
+# let rec listn = function 0 -> nil
+ | n -> cons(random__int 10000,listn (pred n));;
+# heapsort (listn 10);;
+- : list = cons (136, cons (760, cons (1512, cons (2776, cons (3064,
+cons (4536, cons (5768, cons (7560, cons (8856, cons (8952, nil))))))))))
+\end{verbatim}
+
+Some tests on longer lists (100000 elements) show that the program is
+quite efficient for Caml code.
+
+\asubsection{Balanced trees}
+
+The file {\tt Avl\_prog.v} contains the proof of insertion in binary
+balanced trees (AVL). Here we choose to instantiate such trees on the
+type {\tt string} of Caml Light (for instance to get efficient
+dictionary); as above we must realize the decidability of the order
+relation. It gives the following commands:
+
+\begin{coq_eval}
+Reset Initial.
+\end{coq_eval}
+\begin{coq_example*}
+Require Extraction.
+Require Avl_prog.
+\end{coq_example*}
+\begin{coq_eval}
+Pwd.
+\end{coq_eval}
+\begin{coq_example}
+ML Import Constant string == string : Set.
+ML Import Inductive bool [ true false ] ==
+ Inductive BOOL : Set := TRUE : BOOL
+ | FALSE : BOOL.
+ML Import Constant lt_string == lt_string : string->string->BOOL.
+Link a := string.
+Link inf_dec :=
+ [x,y:string]Cases (lt_string x y) of
+ TRUE => left
+ | FALSE => right
+ end.
+Write CamlLight File "avl" [rot_d rot_g rot_gd insert].
+\end{coq_example}
+
+Notice that we do not want the constants {\tt rot\_d}, {\tt rot\_g}
+and {\tt rot\_gd} to be expanded in the function {\tt insert}, and
+that is why we added them in the list of required functions. It makes
+the resulting program clearer, even if it becomes less efficient.
+
+Let us insert random words in an initially empty tree to check that it
+remains balanced:
+\begin{verbatim}
+% camllight
+# include "avl";;
+# let add a t = match insert a t with
+ h_eq x -> x
+ | h_plus x -> x ;;
+# let rdmw () = let s = create_string 5 in
+ for i = 0 to 4 do
+ set_nth_char s i (char_of_int (97+random__int 26))
+ done ; s ;;
+# let rec built = function 0 -> nil
+ | n -> add (rdmw()) (built (pred n));;
+# built 10;;
+- : abe = node ("ogccy", node ("gmygy", node ("cwqug", node ("cjyrc", nil, ...
+
+
+# let rec size = function
+ nil -> 0
+ | node(_,t1,t2,_) -> 1+(max (size t1) (size t2)) ;;
+# let rec check = function
+ nil -> true
+ | node(_,a1,a2,_) ->
+ let t1 = size a1 and t2 =size a2 in
+ if abs(t1-t2)>1 then false else (check a1) & (check a2) ;;
+
+# check (built 100);;
+- : bool = true
+\end{verbatim}
+
+
+\section{Bugs}
+
+Surely there are still bugs in the {\tt Extraction} module.
+You can send your bug reports directly to the author
+(at \textsf{Jean-Christophe.Filliatre$@$lri.fr}) or to the \Coq\
+mailing list (at \textsf{coq$@$pauillac.inria.fr}).
+
+% $Id$