In this lecture, we learn how to do proofs with propositional logical connectives:
False
True
P /\ Q
(i.e., and)P \/ Q
(i.e., or)~P
(i.e., not)We then show how all these connectives can be encoded using only forall
and ->
.
P: PropFalse -> PP: PropFalse -> Pdestruct H. Qed.P: Prop
H: FalsePP: PropP -> P /\ TrueP: PropP -> P /\ TrueP: Prop
H: PP /\ TrueP: Prop
H: PPP: Prop
H: PTrueconstructor. Qed.P: Prop
H: PTrueP, Q: PropP /\ Q -> Q /\ PP, Q: PropP /\ Q -> Q /\ PP, Q: Prop
H: P /\ QQ /\ PP, Q: Prop
HP: P
HQ: QQ /\ PP, Q: Prop
HP: P
HQ: QQP, Q: Prop
HP: P
HQ: QPapply HQ.P, Q: Prop
HP: P
HQ: QQapply HP. Qed.P, Q: Prop
HP: P
HQ: QPP, Q, R: PropP \/ Q -> (P -> R) /\ (Q -> R) -> RP, Q, R: PropP \/ Q -> (P -> R) /\ (Q -> R) -> RP, Q, R: Prop
HOr: P \/ Q
HAnd: (P -> R) /\ (Q -> R)RP, Q, R: Prop
HOr: P \/ Q
HPR: P -> R
HQR: Q -> RRP, Q, R: Prop
H: P
HPR: P -> R
HQR: Q -> RRP, Q, R: Prop
H: Q
HPR: P -> R
HQR: Q -> RRP, Q, R: Prop
H: P
HPR: P -> R
HQR: Q -> RRapply H.P, Q, R: Prop
H: P
HPR: P -> R
HQR: Q -> RPP, Q, R: Prop
H: Q
HPR: P -> R
HQR: Q -> RRapply H. Qed.P, Q, R: Prop
H: Q
HPR: P -> R
HQR: Q -> RQP, Q: Prop~ (P \/ Q) -> ~ P /\ ~ QP, Q: Prop~ (P \/ Q) -> ~ P /\ ~ QP, Q: Prop
H: ~ (P \/ Q)~ P /\ ~ QP, Q: Prop
H: ~ (P \/ Q)~ PP, Q: Prop
H: ~ (P \/ Q)~ QP, Q: Prop
H: ~ (P \/ Q)~ PP, Q: Prop
H: ~ (P \/ Q)P -> FalseP, Q: Prop
H: ~ (P \/ Q)
HP: PFalseP, Q: Prop
H: ~ (P \/ Q)
HP: PP \/ Qapply HP.P, Q: Prop
H: ~ (P \/ Q)
HP: PPP, Q: Prop
H: ~ (P \/ Q)~ QP, Q: Prop
H: ~ (P \/ Q)Q -> FalseP, Q: Prop
H: ~ (P \/ Q)
HQ: QFalseP, Q: Prop
H: ~ (P \/ Q)
HQ: QP \/ Qapply HQ. Qed.P, Q: Prop
H: ~ (P \/ Q)
HQ: QQP, Q: Prop~ (P /\ Q) -> ~ P \/ ~ QP, Q: Prop~ (P /\ Q) -> ~ P \/ ~ QP, Q: Prop
H: ~ (P /\ Q)~ P \/ ~ QP, Q: Prop
H: ~ (P /\ Q)~ PP, Q: Prop
H: ~ (P /\ Q)
HP: PFalseP, Q: Prop
H: ~ (P /\ Q)
HP: PP /\ QP, Q: Prop
H: ~ (P /\ Q)
HP: PPP, Q: Prop
H: ~ (P /\ Q)
HP: PQ(* We cannot prove this in Coq as it is not constructively valid. *) Abort.P, Q: Prop
H: ~ (P /\ Q)
HP: PQ
We can prove it if we assume the law of excluded middle.
Axiom excluded_middle : forall (P : Prop), P \/ ~P.P, Q: Prop~ (P /\ Q) -> ~ P \/ ~ Q(* Exercise! *) Admitted.P, Q: Prop~ (P /\ Q) -> ~ P \/ ~ Q
forall
and ->
Next, we show how to define the logical connectives using only forall
and ->
.
Definition Fals := forall (P : Prop), P.P: PropFals -> PP: PropFals -> PP: Prop(forall P : Prop, P) -> Papply H. Qed.P: Prop
H: forall P : Prop, PPFals <-> FalseFals <-> FalseFals -> FalseFalse -> FalsFals -> Falseapply H.H: FalsFalseFalse -> Falsdestruct H. Qed. Definition not (P : Prop) : Prop := P -> Fals. Definition Tru := not Fals.H: FalseFalsTruTrunot FalsFals -> Falsapply H. Qed.H: FalsFalsTru <-> TrueTru <-> TrueTru -> TrueTrue -> TruTru -> Trueconstructor.H: TruTrueTrue -> Truapply Tru_intro. Qed. Definition and (P Q : Prop) : Prop := forall (R : Prop), (P -> Q -> R) -> R.H: TrueTruP, Q: Propand P Q -> PP, Q: Propand P Q -> PP, Q: Prop
H: and P QPP, Q: Prop
H: forall R : Prop, (P -> Q -> R) -> RPP, Q: Prop
H: forall R : Prop, (P -> Q -> R) -> RP -> Q -> Papply H1. Qed.P, Q: Prop
H: forall R : Prop, (P -> Q -> R) -> R
H1: P
H2: QPP, Q: Propand P Q -> QP, Q: Propand P Q -> QP, Q: Prop
H: and P QQP, Q: Prop
H: forall R : Prop, (P -> Q -> R) -> RQP, Q: Prop
H: forall R : Prop, (P -> Q -> R) -> RP -> Q -> Qapply H2. Qed.P, Q: Prop
H: forall R : Prop, (P -> Q -> R) -> R
H1: P
H2: QQP, Q: PropP -> Q -> and P QP, Q: PropP -> Q -> and P QP, Q: Prop
HP: P
HQ: Qand P QP, Q: Prop
HP: P
HQ: Qforall R : Prop, (P -> Q -> R) -> RP, Q: Prop
HP: P
HQ: Q
R: Prop
H: P -> Q -> RRP, Q: Prop
HP: P
HQ: Q
R: Prop
H: P -> Q -> RPP, Q: Prop
HP: P
HQ: Q
R: Prop
H: P -> Q -> RQexact HP.P, Q: Prop
HP: P
HQ: Q
R: Prop
H: P -> Q -> RPexact HQ. Qed.P, Q: Prop
HP: P
HQ: Q
R: Prop
H: P -> Q -> RQP, Q: Propand P Q -> and Q PP, Q: Propand P Q -> and Q PP, Q: Prop
H: and P Qand Q PP, Q: Prop
H: and P QQP, Q: Prop
H: and P QPP, Q: Prop
H: and P QQapply H.P, Q: Prop
H: and P Qand P QP, Q: Prop
H: and P QPapply H. Qed.P, Q: Prop
H: and P Qand P QP, Q: Propand P Q <-> P /\ QP, Q: Propand P Q <-> P /\ QP, Q: Propand P Q -> P /\ QP, Q: PropP /\ Q -> and P QP, Q: Propand P Q -> P /\ QP, Q: Prop
H: and P QP /\ QP, Q: Prop
H: and P QPP, Q: Prop
H: and P QQapply (and_elim_left P Q H).P, Q: Prop
H: and P QPapply (and_elim_right P Q H).P, Q: Prop
H: and P QQP, Q: PropP /\ Q -> and P QP, Q: Prop
H: P /\ Qand P QP, Q: Prop
HP: P
HQ: Qand P QP, Q: Prop
HP: P
HQ: QPP, Q: Prop
HP: P
HQ: QQapply HP.P, Q: Prop
HP: P
HQ: QPapply HQ. Qed.P, Q: Prop
HP: P
HQ: QQ
We can define our own tactics similar to the built-in tactics
Ltac destruct_and H := pose proof (and_elim_left _ _ H) as H1; pose proof (and_elim_right _ _ H) as H2; clear H. Ltac split_and := apply and_intro.P, Q: Propand P Q -> and Q PP, Q: Propand P Q -> and Q PP, Q: Prop
H: and P Qand Q PP, Q: Prop
H1: P
H2: Qand Q PP, Q: Prop
H1: P
H2: QQP, Q: Prop
H1: P
H2: QPapply H2.P, Q: Prop
H1: P
H2: QQapply H1. Qed. Definition or (P Q : Prop) : Prop := forall (R : Prop), (P -> R) -> (Q -> R) -> R.P, Q: Prop
H1: P
H2: QPP, Q: PropP -> or P QP, Q: PropP -> or P QP, Q: Prop
HP: Por P QP, Q: Prop
HP: Pforall R : Prop, (P -> R) -> (Q -> R) -> RP, Q: Prop
HP: P
R: Prop
H1: P -> R
H2: Q -> RRapply HP. Qed.P, Q: Prop
HP: P
R: Prop
H1: P -> R
H2: Q -> RPP, Q: PropQ -> or P QP, Q: PropQ -> or P QP, Q: Prop
HQ: Qor P QP, Q: Prop
HQ: Qforall R : Prop, (P -> R) -> (Q -> R) -> RP, Q: Prop
HQ: Q
R: Prop
H1: P -> R
H2: Q -> RRapply HQ. Qed.P, Q: Prop
HQ: Q
R: Prop
H1: P -> R
H2: Q -> RQP, Q, R: Propor P Q -> (P -> R) -> (Q -> R) -> RP, Q, R: Propor P Q -> (P -> R) -> (Q -> R) -> RP, Q, R: Prop
HPQ: or P Q
H1: P -> R
H2: Q -> RRP, Q, R: Prop
HPQ: forall R : Prop, (P -> R) -> (Q -> R) -> R
H1: P -> R
H2: Q -> RRP, Q, R: Prop
HPQ: forall R : Prop, (P -> R) -> (Q -> R) -> R
H1: P -> R
H2: Q -> RP -> RP, Q, R: Prop
HPQ: forall R : Prop, (P -> R) -> (Q -> R) -> R
H1: P -> R
H2: Q -> RQ -> Rapply H1.P, Q, R: Prop
HPQ: forall R : Prop, (P -> R) -> (Q -> R) -> R
H1: P -> R
H2: Q -> RP -> Rapply H2. Qed.P, Q, R: Prop
HPQ: forall R : Prop, (P -> R) -> (Q -> R) -> R
H1: P -> R
H2: Q -> RQ -> RP, Q: Propor P Q <-> P \/ Q(* Exercise *) Admitted.P, Q: Propor P Q <-> P \/ Q
As a bonus, we can also encode equality à la Leibniz.
Definition eq (T : Type) (x : T) (y : T) : Prop := forall (P : T -> Prop), P x -> P y.T: Type
x: Teq T x xT: Type
x: Teq T x xapply H. Qed.T: Type
x: T
P: T -> Prop
H: P xP xT: Type
x, y: Teq T x y -> eq T y xT: Type
x, y: Teq T x y -> eq T y xT: Type
x, y: T
H: eq T x yeq T y xapply eq_refl. Qed.T: Type
x, y: T
H: eq T x yeq T x xT: Type
x, y, z: Teq T x y -> eq T y z -> eq T x zT: Type
x, y, z: Teq T x y -> eq T y z -> eq T x zT: Type
x, y, z: T
H1: eq T x y
H2: eq T y zeq T x zapply H1. Qed.T: Type
x, y, z: T
H1: eq T x y
H2: eq T y zeq T x yT: Type
x, y: Teq T x y <-> x = y(* Exercise *) Admitted.T: Type
x, y: Teq T x y <-> x = y
In fact, even implication (->
) can be encoded using forall
!
Definition imp (P Q : Prop) : Prop := forall H : P, Q.P, Q: Propimp P Q <-> (P -> Q)P, Q: Propimp P Q <-> (P -> Q)(* Coq already prints the forall as ->. *) (* Implication is *literally* just a forall! *)P, Q: Prop(P -> Q) <-> (P -> Q)P, Q: Prop(P -> Q) -> P -> QP, Q: Prop(P -> Q) -> P -> QP, Q: Prop(P -> Q) -> P -> Qapply H.P, Q: Prop
H: P -> QP -> QP, Q: Prop(P -> Q) -> P -> Qapply H. Qed.P, Q: Prop
H: P -> QP -> Q
In Coq, the connectives are not defined in terms of forall
, but in terms of Inductive
types.
An inductive type lists all the constructors that make up the type.
For propositions, this means that it lists all the ways to prove the proposition.
There are no ways to prove False.
Inductive False' : Prop := .
There is one way to prove True.
Inductive True' : Prop :=
| I : True'. (* I is the constructor for True' *)
To prove and P Q, we need to provide a proof of P and a proof of Q.
Inductive and' (P Q : Prop) : Prop :=
| conj : P -> Q -> and' P Q. (* conj is the constructor for and' *)
To prove or P Q, we need to provide a proof of P or a proof of Q.
Inductive or' (A B : Prop) : Prop :=
| or_introl : A -> or' A B (* or_introl is the constructor for proving or' from A *)
| or_intror : B -> or' A B. (* or_intror is the constructor for proving or' from B *)
Equality is a more complex example. The only way to prove eq' T x y is if x and y are the same.
Inductive eq' (T : Type) (x : T) : T -> Prop :=
| eq_refl' : eq' T x x. (* eq_refl' is the constructor for eq' *)
These inductive types are manipulated with two tactics:
destruct
: do case analysis on the inductive typeapply [constructor_name]
: apply the constructor to prove the type (we can also use constructor i
for the i-th constructor, or simply constructor
to apply the first matching constructor)P, Q: Propand' P Q -> and' Q PP, Q: Propand' P Q -> and' Q PP, Q: Prop
H: and' P Qand' Q PP, Q: Prop
HP: P
HQ: Qand' Q PP, Q: Prop
HP: P
HQ: QQP, Q: Prop
HP: P
HQ: QPapply HQ.P, Q: Prop
HP: P
HQ: QQapply HP. Qed.P, Q: Prop
HP: P
HQ: QPP, Q: Propor' P Q -> or' Q PP, Q: Propor' P Q -> or' Q PP, Q: Prop
H: or' P Qor' Q PP, Q: Prop
HP: Por' Q PP, Q: Prop
HQ: Qor' Q PP, Q: Prop
HP: Por' Q Papply HP.P, Q: Prop
HP: PPP, Q: Prop
HQ: Qor' Q Papply HQ. Qed.P, Q: Prop
HQ: QQT: Type
x, y: Teq' T x y -> eq' T y xT: Type
x, y: Teq' T x y -> eq' T y xT: Type
x, y: T
H: eq' T x yeq' T y xapply eq_refl'. Qed.T: Type
x: Teq' T x x