Previous Up Next

Chapter 19  Program

Matthieu Sozeau





The status of Program is experimental.

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 18). 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[115], 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 [105] 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 Objective Caml, 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.

19.1  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 match operation (section 4.5.4).

The next two commands are similar to their standard counterparts Definition (section 1.3.2) and Fixpoint (section 1.3.4) in that they define constants. However, they may require the user to prove some goals to construct the final definitions. Note: every subtac definition must end with the Defined vernacular.

19.1.1  Program Definition ident := term.

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.


Error messages:

  1. ident already exists


Variants:

  1. Program Definition ident :term1 := term2.
    It interprets the type term1, potentially generating proof obligations to be resolved. Once done with them, we have a Coq type term1'. It then checks that the type of the interpretation of term2 is coercible to term1', and registers ident as being of type term1' once the set of obligations generated during the interpretation of term2 and the aforementioned coercion derivation are solved.
  2. Program Definition ident binder1bindern :term1 := term2.
    This is equivalent to
    Program Definition ident : forall binder1bindern, term1 := fun binder1bindern => term2 .


Error messages:

  1. In environment the term: term2 does not have type term1.
    Actually, it has type term3.


See also: Sections 6.2.4, 6.2.5, 8.5.5

19.1.2  Program Fixpoint ident params {order} : type := term

The structural fixpoint operator behaves just like the one of Coq (section 1.3.4), except it may also generate obligations.

Coq < Program Fixpoint div2 (n : nat) : { x : nat | n = 2 * x \/ n = 2 * x + 1 } :=
Coq <   match n with
Coq <   | S (S p) => S (div2 p)
Coq <   | _ => O
Coq <   end.
2 obligation(s) remaining

Here we have one obligation for each branch (branches for 0 and (S 0) are automatically generated by the pattern-matching compilation algorithm):

Coq <   Obligations.
2 obligation(s) remaining: 
Obligation 1 of div2:
forall (div2 : forall n : nat, {x : nat | n = 2 * x \/ n = 2 * x + 1})
  (n p : nat),
S (S p) = n ->
n = 2 * S (proj1_sig (div2 p)) \/ n = 2 * S (proj1_sig (div2 p)) + 1.
Obligation 2 of div2:
(forall n : nat, {x : nat | n = 2 * x \/ n = 2 * x + 1}) ->
forall n wildcard : nat, wildcard = n -> n = 2 * 0 \/ n = 2 * 0 + 1.

You can use a well-founded order or a measure as termination orders using the syntax:

Coq < Definition id (n : nat) := n.
id is defined

Coq < 
Coq < Program Fixpoint div2 (n : nat) {measure id n} : { x : nat | n = 2 * x \/ n = 2 * x + 1 } :=
Coq <   match n with
Coq <   | S (S p) => S (div2 p)
Coq <   | _ => O
Coq <   end.
div2 has type-checked, generating 3 obligation(s)
2 obligation(s) remaining

19.1.3  Program Lemma ident : type.

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.

19.1.4  Solving obligations

The following commands are available to manipulate obligations:


Previous Up Next