What kind of an object is a proof? Following the
propositions-as-types principle, Coq models proofs as terms.
According to this principle, proofs are terms of a typed lambda
calculus such that the unique type of a proof term is the proposition
the proof term establishes, and proof checking amounts to type
checking. In programming languages we have
program : type
while in proof systems we have
proof : proposition
In both cases we have a typing relations that relates terms (which may represent programs or proofs) with types (which may represent types of programs or propositions). The propositions-as-types principle is often called Curry Howard correspondence, a catchy phrase that neglects the contributions of researchers like de Bruijn and Martin-Löf.
Consider the following formulas:
forall X, X -> X
forall X Y, (X -> Y) -> (Y -> Z) -> X -> Z
If X and Y range over types (i.e., X Y: Type), then the formulas are polymorphic types that take polymorphic functions as values. The following terms do have theses types.
fun (X: Type) (x:X) => x
fun (X Y: Type) (f:X->Y) (g:Y->Z) (x:X) => g(f x)
Now consider the above formulas for the case where X and Y range over propositions (i.e., X Y: Prop). Then both formulas are propositions and the terms
fun (X: Prop) (x:X) => x
fun (X Y: Prop) (f:X->Y) (g:Y->Z) (x:X) => g(f x)
are proofs of these propositions (since they have the propositions as types). Let's check this out in Coq.
program : type
while in proof systems we have
proof : proposition
In both cases we have a typing relations that relates terms (which may represent programs or proofs) with types (which may represent types of programs or propositions). The propositions-as-types principle is often called Curry Howard correspondence, a catchy phrase that neglects the contributions of researchers like de Bruijn and Martin-Löf.
Consider the following formulas:
forall X, X -> X
forall X Y, (X -> Y) -> (Y -> Z) -> X -> Z
If X and Y range over types (i.e., X Y: Type), then the formulas are polymorphic types that take polymorphic functions as values. The following terms do have theses types.
fun (X: Type) (x:X) => x
fun (X Y: Type) (f:X->Y) (g:Y->Z) (x:X) => g(f x)
Now consider the above formulas for the case where X and Y range over propositions (i.e., X Y: Prop). Then both formulas are propositions and the terms
fun (X: Prop) (x:X) => x
fun (X Y: Prop) (f:X->Y) (g:Y->Z) (x:X) => g(f x)
are proofs of these propositions (since they have the propositions as types). Let's check this out in Coq.
Lemma L1 : forall X: Prop, X -> X.
Proof.
exact (fun (X: Prop) (x:X) => x).
Qed.
Since Coq comes with type inference, we can omit the types in the
proof term.
Goal forall X: Prop, X -> X.
exact (fun X x => x).
We can also construct the proof term with the following proof
script.
Lemma L1' : forall X: Prop, X -> X.
Proof.
intros X x. apply x.
Qed.
Print L1'.
Note that the proof script describes the proof term in
pre-linearized form. Exploiting the propositions-as-types design of
Coq fully, we can also state and proof the lemma as follows.
Definition L1'' : forall X: Prop, X -> X := fun X x => x.
Print L1''.
So there is no real need to use commands like Lemma, Proof, and
Qed. There is also no need to write proof scripts. Rather we can
write definitions to state and prove lemmas. Note that the identifier
of a lemma is bound to the proof of the lemma, not to the claim of the
lemma. However, the claim of the lemma appears as the type of the
identifier of the lemma.
Instead of exact one can also write apply. The apply tactic is much smarter than exact. The apply tactic takes a proof term as argument and tries to apply it to the current claim.
Finally, let's prove a more complicated claim both with a script and with a proof term.
Instead of exact one can also write apply. The apply tactic is much smarter than exact. The apply tactic takes a proof term as argument and tries to apply it to the current claim.
Finally, let's prove a more complicated claim both with a script and with a proof term.
Definition Contra := forall P Q : Prop, (~P -> ~Q) -> Q -> P.
Definition Peirce := forall P Q : Prop, ((P -> Q) -> P) -> P.
Lemma contra2peirce : Contra -> Peirce.
Proof.
intros C P Q. apply C.
intros f g. apply f. apply g.
intro p. apply False_ind. apply f. apply p.
Qed.
Lemma contra2peirce' : Contra -> Peirce.
Proof.
exact (fun C P Q => C P ((P->Q)->P) (fun f g => f (g (fun p => False_ind Q (f p))))).
Qed.
This example shows that the automation that comes with the apply
tactic is helpful because it frees us from giving the propositional
arguments of contra. The tactic tauto can prove any tautology of
contructive propositional logic. Using it, we can shorten the proof
script considerably.
Lemma contra2peirce'' : Contra -> Peirce.
Proof.
intros C P Q. apply C. tauto.
Qed.
It turns out that the proof term tauto finds is not as nice as
the one we gave. See yourself.
Print contra2peirce''.
This page has been generated by coqdoc