exact & apply
exact provides a proof term directly. applyuses a lemma or hypothesis that might need additional arguments.
exact: Direct Proof
Use exact when you have exactly what you need to prove the goal:
1example (h : 2 + 2 = 4) : 2 + 2 = 4 := by2 exact h3 -- h has exactly the type we need45example : True := by6 exact trivial7 -- trivial : True89example (a b : Nat) (h : a = b) : a = b := by10 exact hexact closes the goal immediately. If the provided term doesn't have the right type, Lean gives an error.
Using exact with Library Lemmas
1example (n : Nat) : n + 0 = n := by2 exact Nat.add_zero n3 -- Nat.add_zero : ∀ n, n + 0 = n4 -- Applied to n gives: n + 0 = n ✓56example (a b : Nat) : a + b = b + a := by7 exact Nat.add_comm a b89example : ∀ n : Nat, n = n := by10 exact fun n => rflexact e succeeds when e has exactly the same type as the goal. It's like saying "here is the proof."apply: Working Backwards
apply is like exact, but it can leave "holes" for arguments you don't have yet:
1example (a b c : Nat) (hab : a = b) (hbc : b = c) : a = c := by2 apply Eq.trans3 -- Eq.trans : a = b → b = c → a = c4 -- Goal 1: a = ?middle5 -- Goal 2: ?middle = c6 · exact hab -- Provide first equality7 · exact hbc -- Provide second equalityapply works backwards from the goal. If a lemma says "A → B" and your goal is B, apply creates a new goal: prove A.
apply with Implications
1example (h : 1 = 1 → 2 = 2) : 2 = 2 := by2 apply h3 -- Goal becomes: 1 = 14 rfl56example (P Q : Prop) (h : P → Q) (hp : P) : Q := by7 apply h8 -- Goal becomes: P9 exact hpapply vs exact
1-- When the lemma fits exactly, both work:2example (n : Nat) : n + 0 = n := by3 exact Nat.add_zero n45example (n : Nat) : n + 0 = n := by6 apply Nat.add_zero7 -- Lean infers n from the goal89-- But apply is more flexible:10example (a b c : Nat) (h : a = b) : a + c = b + c := by11 apply congrArg (· + c)12 -- Creates goal: a = b13 exact hexact requires you to fill in all arguments.apply lets Lean infer what it can and creates subgoals for the rest.Common Patterns
Using Hypotheses
1example (P Q R : Prop) (hpq : P → Q) (hqr : Q → R) (hp : P) : R := by2 apply hqr3 -- Goal: Q4 apply hpq5 -- Goal: P6 exact hpTransitivity
1example (a b c d : Nat) (h1 : a = b) (h2 : b = c) (h3 : c = d) : a = d := by2 apply Eq.trans3 · apply Eq.trans4 · exact h15 · exact h26 · exact h378-- Or more concisely:9example (a b c d : Nat) (h1 : a = b) (h2 : b = c) (h3 : c = d) : a = d := by10 exact Eq.trans (Eq.trans h1 h2) h3Congruence
1-- If a = b, then f a = f b2example (f : Nat → Nat) (a b : Nat) (h : a = b) : f a = f b := by3 apply congrArg4 exact h56-- Or just:7example (f : Nat → Nat) (a b : Nat) (h : a = b) : f a = f b := by8 rw [h]The assumption Tactic
assumption searches your hypotheses for an exact match:
1example (P Q : Prop) (hp : P) (hq : Q) : P := by2 assumption3 -- Automatically finds hp : P45example (a b : Nat) (h1 : a = b) (h2 : b = a) : b = a := by6 assumption7 -- Finds h2Deep Dive: Unification
When you write apply lemma, Lean performsunification—it tries to match the conclusion of the lemma with your goal, figuring out what values the lemma's arguments must have.
1-- Goal: 5 + 0 = 52-- Lemma: Nat.add_zero : ∀ n, n + 0 = n34-- apply Nat.add_zero unifies:5-- n + 0 = n with 5 + 0 = 56-- Solution: n = 5If unification fails (the lemma doesn't match), applygives an error.
exact? and apply?
Not sure which lemma to use? Let Lean search:
1example (n : Nat) : n + 0 = n := by2 exact?3 -- Suggests: exact Nat.add_zero n45example (a b : Nat) : a + b = b + a := by6 apply?7 -- Suggests: exact Nat.add_comm a bThese tactics search Lean's library for lemmas that might work. Very useful for discovering what's available!
Summary
| Tactic | Use When |
|---|---|
| exact e | You have exactly what you need |
| apply lemma | Lemma's conclusion matches goal |
| assumption | Goal matches a hypothesis exactly |
| exact? | Search for matching lemma |