4.3. Reasoning about Connectives and Quantifiers
Lecture 1 presented the rules of the connectives as inference figures. Each figure is an ordinary Lean theorem. An introduction rule has the connective as the outermost symbol of its conclusion and says how to prove it, and an elimination rule has the connective in a hypothesis and says how a proof of it may be used. The display below lists the rules for ∧, ∨ and ↔, with metavariables in the places the rules leave open.
And.intro : ?a → ?b → ?a ∧ ?b And.left : ?a ∧ ?b → ?a And.right : ?a ∧ ?b → ?b Or.inl : ?a → ?a ∨ ?b Or.inr : ?b → ?a ∨ ?b Or.elim : ?a ∨ ?b → (?a → ?c) → (?b → ?c) → ?c Iff.intro : (?a → ?b) → (?b → ?a) → (?a ↔ ?b) Iff.mp : (?a ↔ ?b) → ?a → ?b Iff.mpr : (?a ↔ ?b) → ?b → ?a
The rules for the existential quantifier, truth, falsehood and the classical principles round out the display. Implication and the universal quantifier appear in none of these displays, because both are dependent function types, so their introduction is intro and their elimination is application, the juxtaposition of Lecture 2. Negation needs no rules of its own, since ¬a is defined as a → False, so intro applies to a negated conclusion, as Lecture 1 showed. True.intro is the only rule for truth, and False.elim is the only rule for falsehood. Lean's core logic is constructive, and it offers classical reasoning explicitly through Classical.em and Classical.byContradiction, which rest on added axioms. Both appeared since Lecture 1 and now apply backwards.
Exists.intro : ∀ (w : ?α), ?p w → ∃ x, ?p x Exists.elim : (∃ x, ?p x) → (∀ (w : ?α), ?p w → ?b) → ?b True.intro : True False.elim : False → ?c Classical.em : ∀ (p : Prop), p ∨ ¬p Classical.byContradiction : (¬?a → False) → ?a
A metavariable ?a stands for a term still to be determined. When apply matches the conclusion of the goal with the conclusion of a rule, unification determines some metavariables and leaves the others as new goals, and those usually disappear as the proof proceeds. The proof below applies the introduction rule of ∧ backwards and closes each subgoal with an elimination rule.
namespace Backward
theorem And_swap (a b : Prop) : a ∧ b → b ∧ a := a:Propb:Prop⊢ a ∧ b → b ∧ a
a:Propb:Prophab:a ∧ b⊢ b ∧ a
a:Propb:Prophab:a ∧ b⊢ ba:Propb:Prophab:a ∧ b⊢ a
a:Propb:Prophab:a ∧ b⊢ ?left.a ∧ ba:Propb:Prophab:a ∧ b⊢ Propa:Propb:Prophab:a ∧ b⊢ a
a:Propb:Prophab:a ∧ b⊢ a
a:Propb:Prophab:a ∧ b⊢ a ∧ ?right.ba:Propb:Prophab:a ∧ b⊢ Prop
All goals completed! 🐙
end Backward
The · bullet, used since Lecture 1, focuses each subgoal, and juxtaposition instantiates a rule forwards, passing the hypothesis directly instead of waiting for it to appear as a subgoal. This is a small forward step inside a backward proof, and it avoids the metavariables that apply leaves behind.
namespace Backward
theorem And_swap_braces :
∀ a b : Prop, a ∧ b → b ∧ a := ⊢ ∀ (a b : Prop), a ∧ b → b ∧ a
a:Propb:Prophab:a ∧ b⊢ b ∧ a
a:Propb:Prophab:a ∧ b⊢ ba:Propb:Prophab:a ∧ b⊢ a
a:Propb:Prophab:a ∧ b⊢ b All goals completed! 🐙
a:Propb:Prophab:a ∧ b⊢ a All goals completed! 🐙
end Backward
Juxtaposition also instantiates a universal hypothesis, exactly as in Lecture 2.
namespace Backward
opaque f : ℕ → ℕ
theorem f5_if (h : ∀ n : ℕ, f n = n) : f 5 = 5 := h:∀ (n : ℕ), f n = n⊢ f 5 = 5
All goals completed! 🐙
end Backward
The elimination rule of ∨ performs the case analysis that the tactic cases performed in Lecture 1, and modus_ponens and Not_Not_intro combine the rules seen so far.
namespace Backward
theorem Or_swap (a b : Prop) : a ∨ b → b ∨ a := a:Propb:Prop⊢ a ∨ b → b ∨ a
a:Propb:Prophab:a ∨ b⊢ b ∨ a
a:Propb:Prophab:a ∨ b⊢ a → b ∨ aa:Propb:Prophab:a ∨ b⊢ b → b ∨ a
a:Propb:Prophab:a ∨ b⊢ a → b ∨ a a:Propb:Prophab:a ∨ bha:a⊢ b ∨ a
All goals completed! 🐙
a:Propb:Prophab:a ∨ b⊢ b → b ∨ a a:Propb:Prophab:a ∨ bhb:b⊢ b ∨ a
All goals completed! 🐙
theorem modus_ponens (a b : Prop) : (a → b) → a → b := a:Propb:Prop⊢ (a → b) → a → b
a:Propb:Prophab:a → bha:a⊢ b
a:Propb:Prophab:a → bha:a⊢ a
All goals completed! 🐙
theorem Not_Not_intro (a : Prop) : a → ¬¬ a := a:Prop⊢ a → ¬¬a
a:Propha:ahna:¬a⊢ False
a:Propha:ahna:¬a⊢ a
All goals completed! 🐙
end Backward
For proving statements of propositional logic, the guide offers the following strategies.
-
Look at the conclusion. If it is an implication or a negation,
intromakes progress. -
Look at the hypotheses. A conjunction offers
And.leftandAnd.right, a disjunction offersOr.elim, and an equivalence offersIff.mpandIff.mpr. -
Match the conclusion of the goal with the conclusion of an introduction rule and
applyit. -
Prefer tactics that preserve provability while they make progress, and record the choice points where a tactic commits to a side.
-
When a subgoal repeats a hypothesis,
exactorassumptioncloses it. -
When nothing constructive applies, consider a case analysis on
Classical.em. -
If the proof makes no progress, backtrack to the last choice point and try the other option.
4.3.1. Examples
The examples below apply the rules backwards with apply, instantiate them forwards by juxtaposition, and watch the metavariables that appear along the way.
Example 1. apply And.intro splits the conjunction into two goals, and the trace shows both.
example (a b : Prop) (hab : a ∧ b) : b ∧ a := a:Propb:Prophab:a ∧ b⊢ b ∧ a
a:Propb:Prophab:a ∧ b⊢ ba:Propb:Prophab:a ∧ b⊢ a
a:Propb:Prophab:a ∧ b⊢ ba:Propb:Prophab:a ∧ b⊢ a
a:Propb:Prophab:a ∧ b⊢ b All goals completed! 🐙
a:Propb:Prophab:a ∧ b⊢ a All goals completed! 🐙
Example 2. Juxtaposition closes a goal in one step, passing the hypothesis to the elimination rule.
example (a b : Prop) (hab : a ∧ b) : b := a:Propb:Prophab:a ∧ b⊢ b
All goals completed! 🐙
Example 3. Applying the elimination rule backwards leaves a metavariable ?a in the conclusion, and even a second goal asking for ?a itself. The final exact instantiates both at once.
example (a b : Prop) (hab : a ∧ b) : b := a:Propb:Prophab:a ∧ b⊢ b
a:Propb:Prophab:a ∧ b⊢ ?a ∧ ba:Propb:Prophab:a ∧ b⊢ Prop
a:Propb:Prophab:a ∧ b⊢ ?a ∧ ba:Propb:Prophab:a ∧ b⊢ Prop
All goals completed! 🐙
Example 4. apply Or.inl chooses the left side and leaves its proof as the goal.
example (a b : Prop) (ha : a) : a ∨ b := a:Propb:Propha:a⊢ a ∨ b
a:Propb:Propha:a⊢ a
All goals completed! 🐙
Example 5. apply Or.elim h produces one subgoal per disjunct, and a bullet closes each.
example (a b c : Prop) (h : a ∨ b) (hac : a → c)
(hbc : b → c) : c := a:Propb:Propc:Proph:a ∨ bhac:a → chbc:b → c⊢ c
a:Propb:Propc:Proph:a ∨ bhac:a → chbc:b → c⊢ a → ca:Propb:Propc:Proph:a ∨ bhac:a → chbc:b → c⊢ b → c
a:Propb:Propc:Proph:a ∨ bhac:a → chbc:b → c⊢ a → c a:Propb:Propc:Proph:a ∨ bhac:a → chbc:b → cha:a⊢ c
All goals completed! 🐙
a:Propb:Propc:Proph:a ∨ bhac:a → chbc:b → c⊢ b → c a:Propb:Propc:Proph:a ∨ bhac:a → chbc:b → chb:b⊢ c
All goals completed! 🐙
Example 6. apply Iff.intro splits an equivalence into its two implications.
example (a : Prop) : a ∧ a ↔ a := a:Prop⊢ a ∧ a ↔ a
a:Prop⊢ a ∧ a → aa:Prop⊢ a → a ∧ a
a:Prop⊢ a ∧ a → a a:Prophaa:a ∧ a⊢ a
All goals completed! 🐙
a:Prop⊢ a → a ∧ a a:Propha:a⊢ a ∧ a
All goals completed! 🐙
Example 7. Iff.mp and Iff.mpr extract the two directions of an equivalence hypothesis by juxtaposition.
example (a b : Prop) (hab : a ↔ b) (ha : a) : b := a:Propb:Prophab:a ↔ bha:a⊢ b
All goals completed! 🐙
example (a b : Prop) (hab : a ↔ b) (hb : b) : a := a:Propb:Prophab:a ↔ bhb:b⊢ a
All goals completed! 🐙
Example 8. apply Exists.intro supplies a witness, and the hypothesis at the witness closes what remains.
example (P : ℕ → Prop) (h : P 3) : ∃ n, P n := P:ℕ → Proph:P 3⊢ ∃ n, P n
P:ℕ → Proph:P 3⊢ P 3
All goals completed! 🐙
Example 9. apply Exists.elim h consumes an existential hypothesis and names its witness.
example (α : Type) (P : α → Prop) (Q : Prop)
(hex : ∃ x, P x) (h : ∀ x, P x → Q) : Q := α:TypeP:α → PropQ:Prophex:∃ x, P xh:∀ (x : α), P x → Q⊢ Q
α:TypeP:α → PropQ:Prophex:∃ x, P xh:∀ (x : α), P x → Q⊢ ∀ (x : α), P x → Q
α:TypeP:α → PropQ:Prophex:∃ x, P xh:∀ (x : α), P x → Qa:αhPa:P a⊢ Q
All goals completed! 🐙
Example 10. Three one-line proofs. intro applies to a negated conclusion, True.intro is the only rule for truth, and apply False.elim closes any goal from a proof of False, since falsehood has no introduction rule.
example : ¬False := ⊢ ¬False
h:False⊢ False
All goals completed! 🐙
example : True := ⊢ True
All goals completed! 🐙
example (a : Prop) (h : False) : a := a:Proph:False⊢ a
a:Proph:False⊢ False
All goals completed! 🐙