Exercices for Coq

Benjamin Werner

Giens, 1999

Abstract: This text is meant to be viewed through a browser like netscape. It is the possible to copy and paste from it into your Coq window.

1  Pointers

The system is freely available by ftp. It can be found, together with various information, on


There is an e-mail hotline coq@pauillac.inria.fr and and moderated mailing-list coq-club@pauillac.inria.fr.

For people looking about more theoretical references about program extraction (for functional programs), they can have a look at a paper by Christine Paulin and myself (Journal of Symbolic Computation, 1993); go to my home-page (coq.inria.fr/~werner/) look for the pointer ``some publications'' and then some file with JSC in the name...

2  Other documentation

The user's manual is available on-line here for the machines provided by the school, or somewhere else if you have installed Coq on your machine.

3  Propositional tautologies

3.1  (A->B->C)->A->(A->B)->C

We launch this goal by:
Variable A,B,C:Prop.
Lemma Ex1 : (A->B->C)->A->(A->B)->C.
There are various ways to prove it. One is use the automated tactic Tauto. Another automated tactic is Auto, which is often usefull. It does systematicaly Intros and the tries to apply all the local hypotheses as well as the lemmas of the Hint database. A lemma L is added to the database by:
Hints Resolve L.
If Auto manages to solve this goal, it is because this can be done only with introductions and local Apply's:
Intros c a b.
Apply c. (* generates two subgoals *)
Exact a.
Apply b. (* we start solving the secong goal *)
Exact a.
A more primitive way is, in this case, quite easy to give the direct proof of this proposition.
Exact [c,a,b](c a (b a)).
Notice that we here do not have to provide the types of a,b and c in the abstractions, since they can obviously be infered. The explicit proof would be:
Exact [c:A->B->C][a:A][b:A->B](c a (b a)).

3.2  Reminder

3.3  conjunctions: (A->B->C)/\A/\(A->B)->(C/\A)

This hypothesis in this proposition are obviously equivalent to the previous ones, but we have to deal with the conjunctions. Conjunctions in hypotheses are broken appart with Elim. Here we actually have two nested conjunctions:
Intros h1.
Elim h1.
Intros h2 h3.
Elim h3.
Intros h4 h5.
To prove the conjunction, we prove separately its two components by Split.
(* The first part is similar to the previous example *)
Apply h2.
Exact h4.
Apply h5; Exact h4.
(* the last goal *)
Exact h4.

3.4  disjunctions:A->(B\/(A->C))->(C\/B)

Again, in the hypotheses disjunctions are eliminated by Elim. You the get two cases corresponding to the two branches of the disjunction.
Intros a d.
Elim d.
To prove a disjunction, one can use Left and Right to chose the branch to be proven.
(* first case: B is true *)
Intros b.
Exact b.
(* second case: A->C  *)
Intros c.
Apply c; Exact a.

4  Proofs by induction

The principles are the same as before, but elimination over natural numbers yields an induction hypothesis, since the latter is a recursive data type.

We want to prove that addition is commutative. Let us recall its definition:
Fixpoint plus [n:nat] : nat -> nat :=
  Cases m of
    O => m
  | (S p) => (S (plus n m))
Because of its definition, addition verifies two congruences, namely:
(plus  O  n) |> n
(plus  (S nm) |> (S (plus  n m))
We reasoning by induction to prove that the same equalities hold with respect to the second argument.

4.1  (n:nat)(plus n O)=n

This is done by induction over n. The tactic to use equalities in order to change the current goal is Rewrite, a possible tactic to prove reflexive equalities is Trivial.
Lemma p0 : (n:nat)(plus n O)=n.
Intro n; Elim n.
 (* we now have two cases. The base case is trivial. *)
(* The second case is n=(S p) *)
Intros p IH.
Simpl. (* uses the reduction *)
Rewrite IH.

4.2  (n,m:nat)(plus n (S m))=(S (plus n m))

Again, an induction over n.
Lemma pS : (n,m:nat)(plus n (S m))=(S (plus n m)).
Intros n m.
Elim n.
Simpl; Trivial.
(* the recursive case *)
Intros p IH.
Rewrite IH.

4.3  commutativity

Using these two lemmas, try to prove the commutativity.

4.4  transitivity of <

Prov that le is transitive. This is an induction over the proof of a recursive predicate.

5  Euclidean division

In order to avoid the condition d 0 a possible way is to state:

(a,b:nat)(EX q | (EX r | a=(plus (mult (S b) q) r) /\ (le r b))).

The nice point is that the proof really reflects Euclid's algorithm (since we are in constructive logic). The proof is by induction over a. Think of the algorithm to understand how to do the proof !

At some point, we will need to decide which one of two natural numbers is greater. Logicaly, this corresponds to a proof of:
(a,b:nat)(le a b)\/(lt b a)
or some equivalent proposition. When a proof of this disjunction is eliminated, we are left with two cases, one corresponding to the case a<= b and the other one to b >a.

To find this lemma without having to prove it, load the arithmetic library:
Require Arith.
and look for the lemmas ending by a disjunction:
Search or.

6  Program extraction

Here are just a few words about extraction of functional programs. The computational version of the existential quantifier is written {x:A|P}.

For instance, the proposition

(a,b:nat){r:nat | (EX q | a=(plus (mult (S b) q) r) /\ (le r b))}

is the specification of the mod function, computing the reminder of the division of a by (S b). The quotient q will not appear in the extracted program, allthough its existence is part of the specification.

Below is a proof of this specification and how the ML program can be extracted.

Lemma mod : (a,b:nat)
        {r:nat | (EX q:nat | a=(plus (mult (S b) q) r)/\(le r b))}.

Induction a.
Intros; Split with O; Split with O; Simpl.
Replace (plus (mult b (0)) (0)) with (mult b O); Auto.

Apply le_O_n.

Intros a' ha b.
Elim (ha b).
Intros r.
Intros h2.
Elim (le_or_le_S b r).
Split with O.
Elim h2; Intros q hq.
Split with (S q).
Elim hq; Intros hq1 hq2.
Rewrite hq1.
Replace (plus (mult (S b) q) r) with (plus q (mult b (S q))).

Replace b with r; Simpl.
Replace (plus (plus q (mult r q)) r) with (plus q (plus r (mult r q))).
Replace (mult r (S q)) with (plus r (mult r q)).

Replace (mult r q) with (mult q r).
Replace (mult r (S q)) with (mult (S q) r).

Apply mult_sym.

Apply mult_sym.

Replace (plus (plus q (mult r q)) r) with (plus q (plus (mult r q) r)).
Replace (plus r (mult r q)) with (plus (mult r q) r).
Apply plus_sym.

Apply plus_assoc_l.

Apply le_antisym; Auto.

Apply le_O_n.

Intros; Split with (S r).
Elim h2; Intros q hq; Split with q.
Elim hq; Intros hq1 hq2; Split; Auto.
Rewrite hq1; Auto.
Finaly, we can extract the corresponding ML program.

Require Extraction.
Write Caml File "modulo" [mod].
which produces the file modulo.ml

6.1  full division

If we want to extract the program yielding the reminder r and the quotient q, the best is to define ourselves the double existential quantification.
Inductive eucl_ex [a,b:nat] : Set :=
 eucl_intro : 
      (r,q:nat) a=(plus (mult (S b) q) r)->(le r b)->
            (eucl_ex a b).
The specification is then:
Lemma eucl_div : (a,b:nat)(eucl_ex a b).
and is proven in a similar way to the non-computational version of the division.

This document was translated from LATEX by HEVEA.