calc — Calculational Proofs
calc enables step-by-step proofs that chain equalities and relations, making complex proofs readable and natural.
Basic Equality Chains
calc chains a sequence of equalities. Each step transforms the expression, and Lean verifies that the steps are valid. The result is a proof that reads like a mathematical calculation on paper.
1example (a b c : Nat) : (a + b) + c = (c + b) + a := calc2 (a + b) + c = (b + a) + c := by rw [Nat.add_comm a b]3 _ = c + (b + a) := by rw [Nat.add_comm]4 _ = c + (a + b) := by rw [Nat.add_comm a b]5 _ = (c + a) + b := by rw [Nat.add_assoc]6 _ = (a + c) + b := by rw [Nat.add_comm c a]7 _ = a + (c + b) := by rw [Nat.add_assoc]8 _ = a + (b + c) := by rw [Nat.add_comm c b]9 _ = (b + c) + a := by rw [Nat.add_comm]10 _ = (c + b) + a := by rw [Nat.add_comm b c]Each _ refers to the previous line's right-hand side. This makes chains easy to write: each step picks up where the last left off.
calc makes proofs look like paper calculations. Each step justifies one transformation, and the chain combines them.Using Automation
You can use any tactic to justify a calc step. Use ringfor polynomial identities, omega for integer arithmetic, and simp for definitional simplifications.
1-- calc with ring, omega, simp2example (a b : Int) : (a + b)^2 = a^2 + 2*a*b + b^2 := calc3 (a + b)^2 = (a + b) * (a + b) := by ring4 _ = a*a + a*b + b*a + b*b := by ring5 _ = a^2 + 2*a*b + b^2 := by ring67-- Or just one step with ring8example (a b : Int) : (a + b)^2 = a^2 + 2*a*b + b^2 := by ring910-- calc is for when you want to show the reasoning11example (n : Nat) (h : n > 5) : n + 10 > 15 := calc12 n + 10 > 5 + 10 := by omega13 _ = 15 := by rfl14 _ ≥ 15 := by omegaMixed Relations
calc can chain different relations as long as they're transitive together:
1-- Mix = with ≤ and <2example (a b c d : Nat) (h1 : a = b) (h2 : b < c) (h3 : c ≤ d) 3 : a < d := calc4 a = b := h15 _ < c := h26 _ ≤ d := h378-- The chain uses transitivity: a = b < c ≤ d implies a < d910-- Mix = with ≠11example (a b : Nat) (h : a = b + 1) : a ≠ b := calc12 a = b + 1 := h13 _ ≠ b := by omegaJustifications
1-- Various ways to justify steps2example (a b c : Nat) (h : a = b) : a + c = b + c := calc3 a + c = b + c := by rw [h]45example (a b c : Nat) (h : a = b) : a + c = b + c := calc6 a + c = b + c := congrArg (· + c) h78-- Direct application of lemmas9example (a b : Nat) : a + b = b + a := calc10 a + b = b + a := Nat.add_comm a bDeep Dive: How calc Works
calc is syntax sugar that builds a chain of transitivity proofs:
1-- This calc:2example (a b c : Nat) (h1 : a = b) (h2 : b = c) : a = c := calc3 a = b := h14 _ = c := h256-- Is equivalent to:7example (a b c : Nat) (h1 : a = b) (h2 : b = c) : a = c :=8 Eq.trans h1 h2910-- For inequalities, it uses the appropriate transitivity lemmacalc in Tactic Mode
1-- calc can appear inside by blocks2example (a b c : Nat) (h1 : a < b) (h2 : b ≤ c) : a < c := by3 calc a < b := h14 _ ≤ c := h256-- Or as part of a larger proof7example (n : Nat) (h : n > 0) : 2 * n > 0 := by8 have step1 : 2 * n ≥ 2 * 1 := by omega9 calc 2 * n ≥ 2 * 1 := step110 _ = 2 := by ring11 _ > 0 := by omegaReadable Proof Style
1-- calc for readable proofs2theorem sum_first_n (n : Nat) : 2 * (Finset.range (n + 1)).sum id = n * (n + 1) := by3 induction n with4 | zero => simp5 | succ k ih =>6 calc 2 * (Finset.range (k + 2)).sum id 7 = 2 * ((Finset.range (k + 1)).sum id + (k + 1)) := by simp [Finset.sum_range_succ]8 _ = 2 * (Finset.range (k + 1)).sum id + 2 * (k + 1) := by ring9 _ = k * (k + 1) + 2 * (k + 1) := by rw [ih]10 _ = (k + 1) * (k + 2) := by ringcalc shines in mathematical proofs where showing your work matters. It's self-documenting—each step explains itself.Examples
Arithmetic Simplification
1example (x : Int) : (x + 1) * (x - 1) = x^2 - 1 := calc2 (x + 1) * (x - 1) = x*x - x + x - 1 := by ring3 _ = x*x - 1 := by ring4 _ = x^2 - 1 := by ringInequality Chain
1example (a b c : Nat) (h1 : a ≤ 2*b) (h2 : b ≤ c + 1) (h3 : c ≤ 5) 2 : a ≤ 12 := calc3 a ≤ 2*b := h14 _ ≤ 2*(c + 1) := by omega5 _ ≤ 2*(5 + 1) := by omega6 _ = 12 := by rflEquivalence Steps
1example (P Q R : Prop) (h1 : P ↔ Q) (h2 : Q ↔ R) : P ↔ R := calc2 P ↔ Q := h13 _ ↔ R := h2Write a short calc proof that uses one lemma and finishes with rfl.
1example (a b : Nat) : a + b = b + a := calc2 a + b = b + a := by rw [Nat.add_comm]