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:
lean
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.
Key Takeaway
calc makes proofs look like paper calculations. Each step justifies one transformation, and the chain combines them.Using Automation
lean
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:
lean
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
lean
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:
lean
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
lean
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
lean
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 ringℹ
calc shines in mathematical proofs where showing your work matters. It's self-documenting—each step explains itself.Examples
Arithmetic Simplification
lean
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
lean
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
lean
1example (P Q R : Prop) (h1 : P ↔ Q) (h2 : Q ↔ R) : P ↔ R := calc2 P ↔ Q := h13 _ ↔ R := h2