15.2 Some examples
15.2 Some examples
We present here few examples of extractions, taken from the theories library of Coq (into the PROGRAMS directory). We
choose Caml Light as target language, but all can be done in the other
dialects with slight modifications.
15.2.1 Euclidean division
The file Euclid_prog contains the proof of Euclidean division
(theorem eucl_dev). The natural numbers defined in the example
files are unary integers defined by two constructors O and S:
Coq < Inductive nat : Set := O : nat | S : nat -> nat.
To use the proof, we begin by loading the module Extraction and the
file into the Coq environment:
Coq < Require Extraction.
Coq < Require Euclid_prog.
This module contains a theorem eucl_dev, and its extracted term
is of type (b:nat)(a:nat) (diveucl a b), where diveucl is a
type for the pair of the quotient and the modulo.
We can now extract this program to Caml Light:
Coq < Write CamlLight File "euclid" [ eucl_dev ].
Warning: The constant nat_rec is expanded.
Warning: The constant sumbool_rec is expanded.
Warning: The constant le_gt_dec is expanded.
This produces a file euclid.ml containing all the necessary
definitions until let eucl_dev = ... Let us play the resulting program:
# include "euclid";;
# eucl_dev (S (S O)) (S (S (S (S (S O)))));;
- : diveucl = divex (S (S O), S O)
It is easier to test on Caml Light integers:
# 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
15.2.2 Heapsort
Let us see a more complicated example. The file Heap_prog.v
contains the proof of an efficient list sorting algorithm described by
Bjerner. Is is an adaptation of the well-known heapsort
algorithm to functional languages. We first load the files:
Coq < Require Extraction.
Coq < Require Heap_prog.
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 (List_Dom, defined in List.v) and the
decidability of the order relation (inf_total). We proceed as
in section 15.1:
Coq < ML Import int : Set.
int imported.
Coq < Link List_Dom := int.
Constant List_Dom linked to int
Coq < ML Inductive bool [ true false ] ==
Coq < Inductive BOOL : Set := TRUE : BOOL
Coq < | FALSE : BOOL.
ML inductive type(s) bool imported.
Coq < ML Import lt_int : int->int->BOOL.
lt_int imported.
Coq < Link inf_total :=
Coq < [x,y:int]Cases (lt_int x y) of
Coq < TRUE => left
Coq < | FALSE => right
Coq < end.
Warning: the variable TRUE starts with upper case in a pattern
Warning: the variable FALSE starts with upper case in a pattern
Constant inf_total linked to [_:int][_:int]left
Then we extract the Caml Light program
Coq < Write CamlLight File "heapsort" [ heapsort ].
Warning: The constant inf_total is expanded.
Warning: The constant is_heap_rec is expanded.
Warning: The constant sort_rec is expanded.
and test it
# 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))))))))))
Some tests on longer lists (100000 elements) show that the program is
quite efficient for Caml code.
15.2.3 Balanced trees
The file Avl_prog.v contains the proof of insertion in binary
balanced trees (AVL). Here we choose to instantiate such trees on the
type 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:
Coq < Require Extraction.
Coq < Require Avl_prog.
Coq < ML Import string : Set.
string imported.
Coq < ML Inductive bool [ true false ] ==
Coq < Inductive BOOL : Set := TRUE : BOOL
Coq < | FALSE : BOOL.
ML inductive type(s) bool imported.
Coq < ML Import lt_string : string->string->BOOL.
lt_string imported.
Coq < Link a := string.
Constant a linked to string
Coq < Link inf_dec :=
Coq < [x,y:string]Cases (lt_string x y) of
Coq < TRUE => left
Coq < | FALSE => right
Coq < end.
Warning: the variable TRUE starts with upper case in a pattern
Warning: the variable FALSE starts with upper case in a pattern
Constant inf_dec linked to [_:string][_:string]left
Coq < Write CamlLight File "avl" [rot_d rot_g rot_gd insert].
The axiom False_rec is translated into an exception.
Warning: The constant eq_rec is expanded.
Warning: The constant inf_dec is expanded.
Warning: The constant bal_rec is expanded.
Warning: The constant avl_rec is expanded.
Warning: The constant avl_ins_rec is expanded.
Warning: The constant h_eqc is expanded.
Warning: The constant h_plusc is expanded.
Notice that we do not want the constants rot_d, rot_g
and rot_gd to be expanded in the function 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:
% 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
Retrieved by Memoweb from http://pauillac.inria.fr/coq/doc/node.3.4.1.html at 8/10/98