Stefano M. Nicoletti

Lecture 3: From Natural Deduction to Proofs in Lean

1. Aim of the lecture

In the previous lecture, we learned to read a proof state and used tactics such as intro, apply, have, exact, and cases. We now connect those commands to the rules of natural deduction. Tactics are not arbitrary moves: they build and use proofs according to the logical structure of propositions.

The lecture has five aims:

2. Types and inhabitants

A type describes a class of possible objects. A type is inhabited when there is at least one term of that type. If t has type T, we write t : T and say that t inhabits T.

The idea is not limited to Lean. The informal type “moon of Jupiter” is inhabited because Io is a moon of Jupiter. Io is a concrete object satisfying the description expressed by the type NASA Science, Io: Facts.

#check 4          -- 4 : Nat
#check True       -- True : Prop
#check True.intro -- True.intro : True

Nat is inhabited, for example, by 4. True is also inhabited: True.intro has exactly type True. This observation leads from the general relation between terms and types to the relation between proofs and propositions.

3. The Curry-Howard correspondence

Under the Curry-Howard correspondence, propositions and types are two ways of describing the same structure. A proposition specifies what must be proved; the corresponding type specifies what kind of term must be built. A proof of the proposition is a term inhabiting that type Wadler, Propositions as Types.

LogicType theory
propositiontype
proofterm
A → Bfunction from proofs of A to proofs of B
introduction of function construction
elimination of function application

Checking a proof therefore means checking that the constructed term has the declared type. A derivation does not merely certify that a proposition is true: it specifies how to construct its proof Theorem Proving in Lean 4, Propositions and Proofs.

4. Natural deduction and the proof state

Natural deduction presents a proof as a sequence of local steps governed by rules. Each rule shows how to obtain a conclusion from premises. Introduction rules explain how to construct a proof with a particular main connective; elimination rules explain how to use an available proof containing that connective Logic and Proof, Natural Deduction for Propositional Logic.

A judgment has the form Γ ⊢ A. Here Γ is the context of currently available assumptions and A is the conclusion to derive. Lean's proof state has the same organization: the context appears above the turnstile and the goal after it.

Some rules introduce temporary assumptions. To prove A → B, for example, we temporarily assume A and construct B. Once the implication is complete, the assumption has been incorporated into a function from proofs of A to proofs of B.

5. Implication

Implication introduction, →I

Implication introduction, →I

To prove A → B, we introduce an assumption of type A and construct a proof of B. In Lean, intro performs precisely this step.

We want to prove that if it rains and it is cold, then it rains. We introduce the assumption that it rains and is cold; we obtain that it rains by taking the left component; we use exactly that fact.

-- Every example follows the same path: a natural-deduction rule, its reading -- in natural language, a concrete instance, and a term built in the proof state. -- Implication introduction, →I. -- To prove `A → B`, we introduce the temporary assumption `A` and construct `B`. -- Example: if it rains and it is cold, then it rains. theorem lecture03_imp_intro (Rains IsCold : Prop) : Rains IsCold Rains := Rains:PropIsCold:PropRains IsCold Rains Rains:PropIsCold:ProphRainsAndIsCold:Rains IsColdRains Rains:PropIsCold:ProphRainsAndIsCold:Rains IsColdhRains:RainsRains All goals completed! 🐙

Implication elimination, →E

Implication elimination, →E

If we have A → B and A, we apply the first proof to the second and obtain B. This is modus ponens.

-- Implication elimination, →E: modus ponens. -- From `A → B` and `A`, we obtain `B`. -- Example: if it rains, I take the umbrella; it rains; therefore I take it. theorem lecture03_imp_elim (Rains TakeUmbrella : Prop) (hRainsUmbrella : Rains TakeUmbrella) (hRains : Rains) : TakeUmbrella := Rains:PropTakeUmbrella:ProphRainsUmbrella:Rains TakeUmbrellahRains:RainsTakeUmbrella Rains:PropTakeUmbrella:ProphRainsUmbrella:Rains TakeUmbrellahRains:RainshTakeUmbrella:TakeUmbrellaTakeUmbrella All goals completed! 🐙

hRainsUmbrella behaves as a function: it receives a term of type Rains and returns a term of type TakeUmbrella.

6. Conjunction

Conjunction introduction, ∧I

Conjunction introduction, ∧I

To prove A ∧ B, we must construct both components. Applying And.intro splits the goal into two cases: first A, then B.

-- Conjunction introduction, ∧I. -- From a proof of A and a proof of B, we construct a proof of A ∧ B. theorem lecture03_and_intro (Rains IsCold : Prop) (hRains : Rains) (hIsCold : IsCold) : Rains IsCold := Rains:PropIsCold:ProphRains:RainshIsCold:IsColdRains IsCold Rains:PropIsCold:ProphRains:RainshIsCold:IsColdRainsRains:PropIsCold:ProphRains:RainshIsCold:IsColdIsCold Rains:PropIsCold:ProphRains:RainshIsCold:IsColdRains All goals completed! 🐙 Rains:PropIsCold:ProphRains:RainshIsCold:IsColdIsCold All goals completed! 🐙

The bullets belong to distinct goals, corresponding to the two conjuncts.

Conjunction elimination, ∧Eₗ and ∧Eᵣ

Left conjunction elimination, ∧Eₗ
Right conjunction elimination, ∧Eᵣ

A proof of A ∧ B contains a proof of A and a proof of B. We select the left component with .left and the right component with .right.

theorem lecture03_and_elim_left (Rains IsCold : Prop) (hBoth : Rains IsCold) : Rains := Rains:PropIsCold:ProphBoth:Rains IsColdRains Rains:PropIsCold:ProphBoth:Rains IsColdhRains:RainsRains All goals completed! 🐙
theorem lecture03_and_elim_right (Rains IsCold : Prop) (hBoth : Rains IsCold) : IsCold := Rains:PropIsCold:ProphBoth:Rains IsColdIsCold Rains:PropIsCold:ProphBoth:Rains IsColdhIsCold:IsColdIsCold All goals completed! 🐙

Introduction constructs a conjunction from its components; elimination travels in the opposite direction and retrieves a component.

7. Disjunction

Disjunction introduction, ∨Iₗ and ∨Iᵣ

Left disjunction introduction, ∨Iₗ
Right disjunction introduction, ∨Iᵣ

To prove A ∨ B, it is enough to construct one side, but we must specify which one. Or.inl chooses the left side; Or.inr chooses the right side.

-- Left disjunction introduction, ∨Iₗ. theorem lecture03_or_intro_left (Rains Snows : Prop) (hRains : Rains) : Rains Snows := Rains:PropSnows:ProphRains:RainsRains Snows Rains:PropSnows:ProphRains:RainsRains All goals completed! 🐙
-- Right disjunction introduction, ∨Iᵣ. theorem lecture03_or_intro_right (Rains Snows : Prop) (hSnows : Snows) : Rains Snows := Rains:PropSnows:ProphSnows:SnowsRains Snows Rains:PropSnows:ProphSnows:SnowsSnows All goals completed! 🐙

Disjunction elimination, ∨E

Disjunction elimination, ∨E

If we have A ∨ B, we do not know which side was proved. To obtain one conclusion C, we must derive it both in the A case and in the B case.

-- Disjunction elimination, ∨E. -- From `A ∨ B`, `A → C`, and `B → C`, we obtain C by cases. theorem lecture03_or_elim (Rains Snows TakeUmbrella : Prop) (hRainsOrSnows : Rains Snows) (hRainsUmbrella : Rains TakeUmbrella) (hSnowsUmbrella : Snows TakeUmbrella) : TakeUmbrella := Rains:PropSnows:PropTakeUmbrella:ProphRainsOrSnows:Rains SnowshRainsUmbrella:Rains TakeUmbrellahSnowsUmbrella:Snows TakeUmbrellaTakeUmbrella cases hRainsOrSnows with Rains:PropSnows:PropTakeUmbrella:ProphRainsUmbrella:Rains TakeUmbrellahSnowsUmbrella:Snows TakeUmbrellahRains:RainsTakeUmbrella Rains:PropSnows:PropTakeUmbrella:ProphRainsUmbrella:Rains TakeUmbrellahSnowsUmbrella:Snows TakeUmbrellahRains:RainshTakeUmbrella:TakeUmbrellaTakeUmbrella All goals completed! 🐙 Rains:PropSnows:PropTakeUmbrella:ProphRainsUmbrella:Rains TakeUmbrellahSnowsUmbrella:Snows TakeUmbrellahSnows:SnowsTakeUmbrella Rains:PropSnows:PropTakeUmbrella:ProphRainsUmbrella:Rains TakeUmbrellahSnowsUmbrella:Snows TakeUmbrellahSnows:SnowshTakeUmbrella:TakeUmbrellaTakeUmbrella All goals completed! 🐙

cases eliminates the disjunction by making all possible forms explicit.

8. Negation, truth, and falsity

Negation

In Lean, ¬A is defined as A → False. A proof of ¬A is therefore a function taking every hypothetical proof of A to a contradiction.

Negation introduction, ¬I

To introduce ¬A, we introduce A and construct False.

-- Negation introduction, ¬I. -- To prove `¬A`, we introduce A and derive False. theorem lecture03_not_intro (DrinkCoffee StayAwake : Prop) (hCoffeeAwake : DrinkCoffee StayAwake) (hNotAwake : ¬StayAwake) : ¬DrinkCoffee := DrinkCoffee:PropStayAwake:ProphCoffeeAwake:DrinkCoffee StayAwakehNotAwake:¬StayAwake¬DrinkCoffee DrinkCoffee:PropStayAwake:ProphCoffeeAwake:DrinkCoffee StayAwakehNotAwake:¬StayAwakehDrinkCoffee:DrinkCoffeeFalse DrinkCoffee:PropStayAwake:ProphCoffeeAwake:DrinkCoffee StayAwakehNotAwake:¬StayAwakehDrinkCoffee:DrinkCoffeehStayAwake:StayAwakeFalse DrinkCoffee:PropStayAwake:ProphCoffeeAwake:DrinkCoffee StayAwakehNotAwake:¬StayAwakehDrinkCoffee:DrinkCoffeehStayAwake:StayAwakehContradiction:FalseFalse All goals completed! 🐙
Negation elimination, ¬E

To eliminate a negation, we apply ¬A to A and obtain False.

theorem lecture03_not_elim (LabOpen : Prop) (hOpen : LabOpen) (hNotOpen : ¬LabOpen) : False := LabOpen:ProphOpen:LabOpenhNotOpen:¬LabOpenFalse LabOpen:ProphOpen:LabOpenhNotOpen:¬LabOpenhContradiction:FalseFalse All goals completed! 🐙

Truth and falsity

Truth introduction, ⊤I

True has a canonical constructor and requires no assumptions.

-- Truth introduction, ⊤I. theorem lecture03_true_intro : True := True All goals completed! 🐙 -- Alternatively: trivial

exact True.intro can also be replaced by trivial.

Falsity elimination, ⊥E

False has no constructors. If the context already contains a proof of False, we can eliminate falsity and obtain any proposition. This is the principle of ex falso quodlibet.

-- Falsity elimination, ⊥E. theorem lecture03_false_elim (Rains : Prop) (hContradiction : False) : Rains := Rains:ProphContradiction:FalseRains Rains:ProphContradiction:FalseFalse -- Alternatively: exfalso All goals completed! 🐙

The rule does not let us prove anything arbitrarily: it applies only after a contradiction has been constructed.

9. Biconditional

A proof of A ↔ B contains two functions: one from A to B and one from B to A.

Biconditional introduction, ↔I

Biconditional introduction, ↔I

To prove that “it rains and it is cold” is equivalent to “it is cold and it rains,” we construct both directions.

-- Biconditional introduction, ↔I: construct both directions. theorem lecture03_iff_intro (Rains IsCold : Prop) : Rains IsCold IsCold Rains := Rains:PropIsCold:PropRains IsCold IsCold Rains Rains:PropIsCold:PropRains IsCold IsCold RainsRains:PropIsCold:PropIsCold Rains Rains IsCold Rains:PropIsCold:PropRains IsCold IsCold Rains Rains:PropIsCold:ProphRainsAndIsCold:Rains IsColdIsCold Rains Rains:PropIsCold:ProphRainsAndIsCold:Rains IsColdIsColdRains:PropIsCold:ProphRainsAndIsCold:Rains IsColdRains Rains:PropIsCold:ProphRainsAndIsCold:Rains IsColdIsCold All goals completed! 🐙 Rains:PropIsCold:ProphRainsAndIsCold:Rains IsColdRains All goals completed! 🐙 Rains:PropIsCold:PropIsCold Rains Rains IsCold Rains:PropIsCold:ProphIsColdAndRains:IsCold RainsRains IsCold Rains:PropIsCold:ProphIsColdAndRains:IsCold RainsRainsRains:PropIsCold:ProphIsColdAndRains:IsCold RainsIsCold Rains:PropIsCold:ProphIsColdAndRains:IsCold RainsRains All goals completed! 🐙 Rains:PropIsCold:ProphIsColdAndRains:IsCold RainsIsCold All goals completed! 🐙

Biconditional elimination, ↔Eₗ and ↔Eᵣ

Left-to-right biconditional elimination, ↔Eₗ
Right-to-left biconditional elimination, ↔Eᵣ

Iff.mp extracts the left-to-right direction; Iff.mpr extracts the right-to-left direction.

-- Left-to-right biconditional elimination, ↔Eₗ. theorem lecture03_iff_elim_left (EvenNumber DivisibleByTwo : Prop) (hEquivalence : EvenNumber DivisibleByTwo) (hEvenNumber : EvenNumber) : DivisibleByTwo := EvenNumber:PropDivisibleByTwo:ProphEquivalence:EvenNumber DivisibleByTwohEvenNumber:EvenNumberDivisibleByTwo EvenNumber:PropDivisibleByTwo:ProphEquivalence:EvenNumber DivisibleByTwohEvenNumber:EvenNumberhDirection:EvenNumber DivisibleByTwoDivisibleByTwo EvenNumber:PropDivisibleByTwo:ProphEquivalence:EvenNumber DivisibleByTwohEvenNumber:EvenNumberhDirection:EvenNumber DivisibleByTwohDivisibleByTwo:DivisibleByTwoDivisibleByTwo All goals completed! 🐙
-- Right-to-left biconditional elimination, ↔Eᵣ. theorem lecture03_iff_elim_right (EvenNumber DivisibleByTwo : Prop) (hEquivalence : EvenNumber DivisibleByTwo) (hDivisibleByTwo : DivisibleByTwo) : EvenNumber := EvenNumber:PropDivisibleByTwo:ProphEquivalence:EvenNumber DivisibleByTwohDivisibleByTwo:DivisibleByTwoEvenNumber EvenNumber:PropDivisibleByTwo:ProphEquivalence:EvenNumber DivisibleByTwohDivisibleByTwo:DivisibleByTwohDirection:DivisibleByTwo EvenNumberEvenNumber EvenNumber:PropDivisibleByTwo:ProphEquivalence:EvenNumber DivisibleByTwohDivisibleByTwo:DivisibleByTwohDirection:DivisibleByTwo EvenNumberhEvenNumber:EvenNumberEvenNumber All goals completed! 🐙

After extracting the needed direction, we apply it as an ordinary implication.

10. Choosing a rule

When reading a proof state, ask a few questions. First: what is the main connective of the goal? It often suggests an introduction rule. Second: which compound proofs are already in the context? They suggest elimination rules.

Lean tactic or termNatural-deduction reading
intro hintroduce an assumption
apply Capply a constructor or rule
have h := ...obtain an intermediate fact
exact huse exactly the required term
cases h withconsider the possible cases
h.left, h.righteliminate a conjunction
hAB hAeliminate an implication

This vocabulary describes the structure of the term Lean is constructing and makes the relationship between formal rule, natural-language argument, and proof script explicit.

11. Working strategy

When constructing a proof:

1. read the goal and assumptions; 2. identify the goal's main connective; 3. choose an introduction rule when the goal suggests one; 4. look for a useful elimination rule in the context; 5. name important intermediate results with have; 6. close the goal with exact when the required term is available; 7. verify that every case and subgoal has been solved.

Classroom.lean presents each rule separately. Exercises.lean begins with direct applications and then combines rules into complete arguments. Solutions.lean keeps the proof structure explicit so that each Lean step can be connected to its natural-deduction rule.

12. Sources and further reading