Course5: Proofs as programs
Using Coq as a proof assistant.
Set Implicit Arguments.
Definition Formula := Set.
In the following, we shall introduce some types and
type constructions in Formula as well as some Coq terms
which shall model inference rules on them.
We shall follow the outline:
- true
- false
- implication
- negation
- conjunction
- disjunction
- excluded-middle
- quantifiers
- equality
- first proofs
Let us consider the following inductive types:
with its single constructor (introduction rule):
Constant True
Inductive VRAI : Formula :=
| VRAIintro.
Check VRAIintro.
VRAIintro : VRAI
VRAI has essentially one proof (inhabitant):
its single constructor.
Constant False
Inductive FAUX : Formula :=
.
Having no constructor, FAUX has no introduction rule.
Definition FAUXelim (A: Formula) (f: FAUX) : A :=
match f with
end.
Notice the odd shape of this pattern-matching with no
clause for matching... but indeed FAUX has no constructor!
Check FAUXelim.
FAUXelim
: ∀ A : Formula, FAUX → A
FAUXelim corresponds to the elimination of the absurd,
also known as ex falso sequitur quodlibet.
Implication
Inductive IMP (A B : Formula) : Formula :=
|IMPintro: (A → B) → IMP A B.
Check IMPintro.
IMPintro
: ∀ A B : Formula, (A → B) → IMP A B
Definition IMPelim (A B: Formula) (i: IMP A B) (a: A) : B :=
match i with
|IMPintro f ⇒ f a
end.
Check IMPelim.
IMPelim
: ∀ A B : Formula, IMP A B → A → B
Notice that an alternative, would have been to define IMP
simply as an alias for → :
Definition IMP' (A B: Formula) : Formula := A → B.
We will come back to this later today.
Inductive NEG (A : Formula) : Formula :=
|NEGintro : (A → FAUX) → NEG A.
Check NEGintro.
NEGintro
: ∀ A : Formula, (A → FAUX) → NEG A
Definition NEGelim (A : Formula) (n: NEG A) : A → FAUX :=
match n with
|NEGintro f ⇒ f
end.
Check NEGelim.
NEGelim
: ∀ A : Formula, NEG A → A → FAUX
Negation could also be considered as a defined connective:
Definition NEG' (A : Formula) : Formula := IMP A FAUX.
Inductive ET (A B : Formula) : Formula :=
| ETintro : A → (B → ET A B).
Check ETintro.
ETintro
: ∀ A B : Formula, A → B → ET A B
Definition ETelim1 (A B: Formula) (c: ET A B) : A :=
match c with
|ETintro a b ⇒ a
end.
Definition ETelim2 (A B: Formula) (c: ET A B) : B :=
match c with
|ETintro a b ⇒ b
end.
Check ETelim2.
ETelim2 : ∀ A B : Formula, ET A B → B
Definition EQUIV (A B: Formula) := ET (IMP A B) (IMP B A).
Inductive OU (A B : Formula) : Formula :=
|OUintro1 : A → OU A B
|OUintro2 : B → OU A B.
Arguments OUintro1 {A B}.
Arguments OUintro2 {A B}.
Check @OUintro1.
OUintro1
: ∀ A B : Formula, A → OU A B
Definition OUelim {A B C: Formula}
(d: OU A B) (e: A → C) (f: B → C) :=
match d with
|OUintro1 a ⇒ e a
|OUintro2 b ⇒ f b
end.
Check @OUelim.
OUelim
: ∀ A B C : Formula,
OU A B → (A → C) → (B → C) → C
Shall a proof of a disjunction only be obtained from
a proof of the left disjunct or from the right disjunct?
Is there no third option?
The excluded-middle is a third
option, if you want to accept it.
But there is no computational counter-poart to it: one
shall add it as an axiom, that is as an additional constant
we declare.
Do you remember how to do it?
Section ExcludedMiddle.
Variables A B: Formula.
Variable TiersExclus : (OU A (NEG A)).
Definition PeirceLaw : IMP (IMP (IMP A B) A) A :=
IMPintro (fun (f : IMP (IMP A B) A) ⇒ match TiersExclus with
| OUintro1 PA ⇒ PA
| OUintro2 (NEGintro fnegA) ⇒ match f with
|IMPintro f' ⇒ f' (IMPintro (fun (a: A) ⇒
match (fnegA a) return B with
end)) end
end).
What is this term PeirceLaw ??
End ExcludedMiddle.
Check PeirceLaw.
Quantifiers:
- an arithmetical quantification and
- a general quantification over any type in Set.
Inductive POURTOUTN (B: nat → Formula) : Formula :=
|PTNintro : (∀ (x : nat), B x) → POURTOUTN B.
Arguments PTNintro {B}.
Check @PTNintro.
PTNintro
: ∀ B : nat → Formula,
(∀ x : nat, B x) → POURTOUTN B
Definition POURTOUTNelim {B: nat → Formula}
(f: POURTOUTN B) (t: nat) : B t :=
match f with
|PTNintro g ⇒ g t
end.
Check @POURTOUTNelim.
POURTOUTNelim
: ∀ B : nat → Formula,
POURTOUTN B → ∀ t : nat, B t
Inductive POURTOUT (A : Set) (B: A → Formula) : Formula :=
|PTintro : (∀ (x : A), B x) → POURTOUT B.
Arguments PTintro {A B}.
Definition POURTOUTelim {A: Set} {B: A → Formula}
(f: POURTOUT B) (t: A) : B t :=
match f with
|PTintro g ⇒ g t
end.
Exists quantifier
Inductive ILEXISTEN (B: nat → Formula) : Formula :=
|IENintro : ∀ x: nat, B x → ILEXISTEN B.
Arguments IENintro {B}.
Check @IENintro.
IENintro
: ∀ (B : nat → Formula) (x : nat),
B x → ILEXISTEN B
Be careful in reading this type!!
Let us add some parentheses:
IENintro
: ∀ (B : nat → Formula) (x : nat),
(B x → ILEXISTEN B)
Definition ILEXISTENelim {B: nat → Formula} {C: Formula}
(e: ILEXISTEN B) (f: ∀ x: nat, B x → C) : C :=
match e with
|IENintro t p ⇒ f t p
end.
Check @ILEXISTENelim.
ILEXISTENelim
: ∀ (B : nat → Formula) (C : Formula),
ILEXISTEN B → (∀ x : nat, B x → C) → C
Again, it is useful to add some parentheses to parse
the above type correctly:
ILEXISTENelim
: ∀ (B : nat → Formula) (C : Formula),
ILEXISTEN B → (∀ x : nat, (B x → C)) → C
Inductive ILEXISTE (A: Set) (B: A → Formula) : Formula :=
|IEintro : ∀ x: A, B x → ILEXISTE B.
Arguments IEintro {A B}.
Definition ILEXISTEelim (A: Set) {B: A → Formula} {C: Formula}
(e: ILEXISTE B) (f: ∀ x: A, B x → C) : C :=
match e with
|IEintro t p ⇒ f t p
end.
Equality
Inductive EQN (x : nat) : nat → Formula :=
| EQNintro : EQN x x.
Check EQNintro.
EQNintro
: ∀ x : nat, EQN x x
Definition EQNelim (A: nat → Formula) (m n : nat):
EQN m n → A m → A n :=
fun (Heq: EQN m n) ⇒ fun (x: A m) ⇒
match Heq in (EQN _ a) return A a with
|EQNintro _ ⇒ x
end.
Check EQNelim.
EQNelim
: ∀ (A : nat → Set) (m n : nat),
EQN m n → A m → A n
Inductive EQ (A: Set) (x : A) : A → Formula :=
| EQintro : EQ x x.
Definition EQelim (B: Set) (A: B → Formula) (m n : B):
EQ m n → A m → A n :=
fun (Heq: EQ m n) ⇒ fun (x: A m) ⇒
match Heq in (EQ _ a) return A a with
|EQintro _ ⇒ x
end.
One can state and prove the first properties
about equality :
Definition EQNrefl:
POURTOUTN (fun x ⇒ EQN x x) :=
PTNintro (fun x ⇒ EQNintro x).
Definition EQNtrans : POURTOUTN (fun x ⇒
POURTOUTN (fun y ⇒
POURTOUTN (fun z ⇒
IMP (EQN x y)
(IMP (EQN y z) (EQN x z))))) :=
PTNintro (fun x ⇒
PTNintro (fun y ⇒
PTNintro (fun z ⇒
IMPintro (fun (H : EQN x y) ⇒
IMPintro (fun (G: EQN y z) ⇒
match G in (EQN _ a) return (EQN x a) with
|EQNintro _ ⇒ H
end))))).
Definition EQNsym:
POURTOUTN (fun x ⇒
POURTOUTN (fun y ⇒
IMP (EQN x y) (EQN y x))) :=
PTNintro (fun x ⇒
PTNintro (fun y ⇒
IMPintro (fun (H : EQN x y) ⇒
match H in (EQN _ a) return (EQN a x) with
|EQNintro _ ⇒ EQNintro x
end))).
Check EQNrefl.
Check EQNtrans.
Check EQNsym.
One can state and prove the first properties
about equality even over other individual sorts:
Definition EQrefl (A: Set):
POURTOUT (fun (x:A) ⇒ EQ x x) :=
PTintro (fun x ⇒ EQintro x).
Definition EQtrans (A: Set): POURTOUT (fun (x: A) ⇒
POURTOUT (fun y ⇒
POURTOUT (fun z ⇒
IMP (EQ x y)
(IMP (EQ y z) (EQ x z))))) :=
PTintro (fun x ⇒
PTintro (fun y ⇒
PTintro (fun z ⇒
IMPintro (fun (H : EQ x y) ⇒
IMPintro (fun (G: EQ y z) ⇒
match G in (EQ _ a) return (EQ x a) with
|EQintro _ ⇒ H
end))))).
Definition EQsym (A: Set):
POURTOUT (fun (x: A) ⇒
POURTOUT (fun y ⇒
IMP (EQ x y) (EQ y x))) :=
PTintro (fun x ⇒
PTintro (fun y ⇒
IMPintro (fun (H : EQ x y) ⇒
match H in (EQ _ a) return (EQ a x) with
|EQintro _ ⇒ EQintro x
end))).
Check EQrefl.
Check EQtrans.
Check EQsym.
Module Notations.
Infix "==" := EQ (at level 70).
Infix "⇒" := IMP (at level 70).
Infix "⇔" := EQUIV (at level 70).
Notation "∀" := POURTOUT (at level 70).
Notation "∀N" := POURTOUTN (at level 70).
Notation "∃" := ILEXISTE (at level 70).
Notation "∃N" := ILEXISTEN (at level 70).
Infix "∧" := ET (at level 50).
Infix "∨" := OU (at level 40).
Notation "¬ L" := (NEG L) (at level 65).
End Notations.
Import Notations.
Check PeirceLaw.
Check EQNtrans.
Check EQrefl.
Check EQtrans.
Check EQsym.
Even and Odd numbers
Inductive Even : nat → Formula :=
| Even0 : Even 0
| EvenSSn : ∀ (n: nat), (Even n) → (Even (S (S n))).
Inductive Odd : nat → Formula :=
| Odd1 : Odd 1
| OddSSn : ∀ (n: nat), (Odd n) → (Odd (S (S n))).
It is natural to be willing to prove that any natural
is even or odd. Let us do it !
Fixpoint EO (n: nat) : (OU (Even n) (Odd n)) :=
match n with
|0 ⇒ OUintro1 Even0
|1 ⇒ OUintro2 Odd1
|S ((S p) as m) ⇒ match (EO p) with
|OUintro1 H ⇒ OUintro1 (EvenSSn H)
|OUintro2 H ⇒ OUintro2 (OddSSn H)
end
end.
Check EO.
Definition EvenOrOdd: POURTOUTN (fun (n:nat) ⇒
(OU (Even n) (Odd n))) := PTNintro (EO).
Check EvenOrOdd.
EvenOrOdd
: (∀N) (fun n : nat ⇒ Even n ∨ Odd n)
SKIP THIS!!
Definition EO' : ∀ (n: nat), (OU (Even n) (Odd n)).
Proof.
fix IHn 1.
intro n.
destruct n.
- apply (OUintro1 Even0).
- destruct n.
+ apply (OUintro2 Odd1).
+ destruct (IHn n) as [He | Ho].
× apply (OUintro1 (EvenSSn He)).
× apply (OUintro2 (OddSSn Ho)).
Qed.
Theorem AddComm: POURTOUTN (fun m ⇒
POURTOUTN (fun n ⇒ EQ (m+n) (n+m))).
split. intro m. split. induction m.
- intro n. simpl. induction n.
+ simpl. split.
+ induction n.
× simpl. split.
× simpl. simpl in IHn. rewrite IHn. split.
- intro n. simpl. induction n.
+ simpl. simpl in IHm. rewrite IHm. split.
+ simpl. rewrite <- IHn. rewrite IHm. simpl. rewrite IHm. split.
Defined.
Print AddComm.
Check AddComm.
AddComm
: (∀N)
(fun m : nat ⇒ (∀N) (fun n : nat ⇒ m + n == n + m))
Encounter with the third kind: Prop
Check 0.
Check nat.
Check Set.
Alias for the first level Type(0)
Check Type.
The various levels of the hierarchy are
used to "type types":
Check nat.
Check nat → nat.
Inductive Fin : nat → Set :=
| Zero n : Fin (S n)
| Succ n : Fin n → Fin (S n).
Check ∀ (a: nat), Fin a → Fin a.
Set is Type(0)
Check ∀ (A: Set), A → A.
Here, Type is Type(1)
Check Set → Set.
Here, Type is Type(1)
Check Type → Type.
Here, Type → Type : Type
should be read Type(i) → Type(j) : Type(max(i,j)+1
Since Type(i) : Type(i+1) and Type(j) : Type(j+1)
Inductive List (A: Type): Type :=
|Nil: List A
|Cons: A → List A → List A.
Check List.
Another universe : Prop
The universe of logical statement and proofs
For proofs
Check I.
is the canonical proof of True, hence I : True
Check True.
Check Prop.
Check Prop.
Back to the type hierarchy
Type(...) | Type(3) | Type(2) | Type(1) / \ / \ / \ Set=Type(0) Prop / | \ | \ nat bool bool->nat True False | | \ | O true \ I - (no close proof of False) (fun (x:nat) => 1)
- If Γ ⊢ A:Type and Γ+x:A ⊢ B:Type then Γ ⊢ (∀ x:A,B) : Type
- If Γ ⊢ A: Type(i) and Γ+x:A ⊢ B:Type(j) then
Γ ⊢ A:Type(i) Γ+x:A ⊢ B:Type(j) ________________________________________(Prod-Type) Γ ⊢ (forall x:A,B) : Type(max(i,j))
Terminology about Set vs Prop
- In Set:
- A specification is any type S of the sort Set
- A program is any term t the type of which is a specification.
- In Prop:
- A proposition or statement is any type P of the sort Prop
- A proof is any term t the type of which is a proposition.
Rules for forming dependent product in the Calculus of Constructions:


- simple types
- impredicativity of Prop
- dependency
- higher-order
Stating theorems and proving them using Coq
Entering the proof mode
Subgoals and tactics
Lemma and_commut :
∀ A B : Prop, A ∧ B ↔ B ∧ A.
Proof.
intros. split.
- intros. destruct H. split. assumption. assumption.
- intros. destruct H. split; assumption.
Qed.
When tactics are separated by dots, Coq will execute
them steps-by-steps. One can also use semi-colon ;
to chain tactics : the second tactic is applied to
all subgoals resulting from the first tactic on the
current goal, and so forth. For instance, split;assumption
applies assumption on the two subgoals created by split.
Before a tactic, one may optionally write a bullet, i.e.
one of the character - or + or ×. These bullets
help organizing the proof in a hierarchical way, with
delimitation of each sub-part (enforced by Coq).
Such a proof script is to be saved in a file with a
.v extension, as done in the previous lectures for instance
myproofs.v. Then it can be compiled via the unix command
coqc myproofs.v. If the content of this file is correct,
then a binary file myproofs.vo is produced, allowing
later a fast reload of our proofs (via the Require Import
command).
A detailed study of Coq's built-in logical propositions.
Lemma my_first_proof : True.
Proof.
exact I.
Qed.
Print my_first_proof.
Just about the same as this:
Definition my_first_proof_bis : True := I.
Operators, for building more advanced statements
->, implication
Check nat → nat.
Check True → True.
Lemma proof2 : True → True.
Proof.
exact (fun _ ⇒ I).
Qed.
or step by step :
intro : the tactic of introduction of -> :
A |- B -----------(->intro) |- A-> B
Lemma proof3 : True → True.
Proof.
intro.
Show Proof.
to inspect the proof term being built
assumption.
the axiom rule of natural deduction
Qed.
Print proof3.
Print proof3.
Lemma identity : ∀ (A:Prop), A → A.
Proof.
intros A a.
assumption.
Qed.
Print identity.
forall and its non-dependent version -> are the
only primitive operators.
To introduce them, one has the following introduction
tactics: intro / intros / intros ...
It is possible to name the hypothesis or quantified
variables, otherwise, Coq name them automatically:
it can be convenient but may result in less maintainable
formal proofs.
On the other hand, in order to used an implicative of
universally quantified statement, one uses their elimination:
apply H.
Lemma test : ∀ (A B : Prop), (A→B)->A→B.
Proof.
intros A B f a.
apply f.
assumption. apply a.
exact a.
Qed.
Print test.
Qed.
Print test.
By default, apply work on the goal to be prove,
it is backward-chaining, proving from the conclusion
to the hypothesis.
But one can also specify that apply should be
used on an hypothesis, reasoning in forward-chaining
mode, from the hypotheses to the conclusion:
Lemma test' : ∀ (A B : Prop), (A→B)->A→B.
Proof.
intros A B f a.
apply f in a.
assumption. apply a.
exact a.
Qed.
Print test.
Print test'.
Lemma test'' : ∀ (A B : Prop), (A→B)->A→B.
Proof.
auto.
Qed.
Print test''.
Qed.
Print test.
Print test'.
Lemma test'' : ∀ (A B : Prop), (A→B)->A→B.
Proof.
auto.
Qed.
Print test''.
Check True.
Print True.
Check I.
Check False.
Print False.
no closed construction
Lemma efql : False → ∀ (A:Prop), A.
Proof.
intro fa.
intro A.
destruct fa.
elimination of a False hypothesis
Qed.
Print efql.
Print efql.
Compare with the predifined :
Check False_ind.
Print False_ind.
Check False_rect.
Print False_rect.
negation is a shortcut for ...->False
Check ¬True.
Check True → False.
Lemma attempt : ~True.
Proof.
unfold "~" in *. intro.
/\, conjunction
- introduction is done via the split tactic
- elimination via destruct ...
Parameter A B : Prop.
Lemma conj : A∧B → B∧A.
Proof.
intro H.
destruct H.
or destruct H as [HA HB].
split.
- assumption.
- assumption.
Qed.
- assumption.
- assumption.
Qed.
Check and_ind.
Available bullets for structuring a proof script : - + ×
\/, disjunction
- introduction is done via the left and right tactics
- elimination via destruct ...
Lemma disj : A∨B → B∨A.
Proof.
intro H.
destruct H.
or destruct H as [HA | HB].
- right. assumption.
- left. assumption.
Qed.
- left. assumption.
Qed.
Lemma disj_equiv: A∨ B ↔ B ∨ A.
Proof.
split; intro H;
destruct H; [right | left | right | left]; assumption.
Qed.
Lemma disj_equiv_fail: A∨ B ↔ B ∨ A.
Proof.
split; intro H;
destruct H; (right || left); assumption.
Qed.
Lemma disj_equiv': A∨ B ↔ B ∨ A.
Proof.
split; intro H;
destruct H; ((right; assumption) || (left; assumption)).
Qed.
exists : introduction via : exists ...
elimination via : destruct ...
Lemma example_exists : ∃ x : nat, x = 0.
Proof.
∃ 0. reflexivity.
Qed.
Summary of elementary tactics
- assumption if the current goal is exactly one of the hypothesis (cf. the axiom rule in logic).
- For all primitive connectors (quantification ∀,
implication →):
- introduction via intro (or one of its variants intros,
- elimination via apply H (where H is the name of
- The other connectors (which are actually inductive definitions)
may ideally be introduced by constructor and eliminated by
destruct H.
But the introduction frequently requires more ad-hoc tactics:
- split for a conjunction ∧ (written
/\
) - left and right for a disjunction ∨ (written
\/
) - ∃ ... (written
exists
) for a quantification ∃
- No introduction tactic for False !
- For True (seldom used in Coq), the introduction can
- split for a conjunction ∧ (written
- Some abbreviations:
- A negation ¬A (written
~A
) is just a shortcut for A→False.
- An equivalence A↔B (written
A<->B
) is just a shortcut for (A→B)/\(B→A),
- A negation ¬A (written
- Some automatic tactics : trivial, easy, auto, eauto, intuition, firstorder. See the Coq documentation for more details.
Some more tactics
- reflexivity
- symmetry
- transitivity ... (where you need to give the intermediate
- rewrite ... (give the equality name or lemma to use as a
- rewrite <- ... (right-to-left rewriting)
- induction ... (to do inductive reasoning, to be investigated in the next lectures).
This page has been generated by coqdoc