congr
Apply congruence to break down equality goals. congrreduces proving f a = f b to provinga = b.
❗
Full
congr features require Mathlib. Basic congruence is available in core Lean 4.Basic Usage
lean
1import Mathlib.Tactic.Congr23-- congr breaks down equality goals by congruence4example (a b : Nat) (h : a = b) : a + 1 = b + 1 := by5 congr6 -- Reduces to: a = b7 -- Automatically solved by exact h89example (f : Nat → Nat) (a b : Nat) (h : a = b) : f a = f b := by10 congrKey Takeaway
congr applies the principle: if you apply the same function to equal arguments, you get equal results.Multiple Arguments
lean
1import Mathlib.Tactic.Congr23-- congr handles multiple arguments4example (a b c d : Nat) (h1 : a = c) (h2 : b = d) : a + b = c + d := by5 congr6 · exact h1 -- prove a = c7 · exact h2 -- prove b = d89-- With lists10example (x y : Nat) (xs ys : List Nat) (hx : x = y) (hxs : xs = ys) : 11 x :: xs = y :: ys := by12 congrcongr n
lean
1import Mathlib.Tactic.Congr23-- congr n applies congruence n levels deep4example (a b : Nat) (h : a = b) : (a + 1) * 2 = (b + 1) * 2 := by5 congr 16 -- Only descends one level: a + 1 = b + 178example (a b : Nat) (h : a = b) : (a + 1) * 2 = (b + 1) * 2 := by9 congr 210 -- Descends two levels: a = b💡
Use
congr n to control how deeply congruence is applied. Useful when you only want to match part of the expression.With Structures
lean
1import Mathlib.Tactic.Congr23-- congr works with structure constructors4example (a b c d : Nat) (h1 : a = c) (h2 : b = d) : (a, b) = (c, d) := by5 congr67-- Nested structures8example (a b c d : Nat) (h1 : a = c) (h2 : b = d) : 9 ((a, b), 0) = ((c, d), 0) := by10 congr11 congrgcongr (Generalized Congruence)
lean
1import Mathlib.Tactic.GCongr23-- gcongr handles inequalities and relations, not just equality4example (a b c d : Nat) (h1 : a ≤ c) (h2 : b ≤ d) : a + b ≤ c + d := by5 gcongr67example (a b : Nat) (h : a ≤ b) : 2 * a ≤ 2 * b := by8 gcongrDeep Dive: Congruence Principle
Congruence is the principle that functions preserve equality:
lean
1-- If a = b, then f a = f b2-- More formally: ∀ f a b, a = b → f a = f b34-- This extends to multiple arguments:5-- If a = a' and b = b', then f a b = f a' b'67-- congr applies these principles automaticallycongr with Hypotheses
lean
1import Mathlib.Tactic.Congr23-- Sometimes congr creates subgoals you need to prove4example (n m : Nat) (h : n = m) : n.succ = m.succ := by5 congr67-- congr might create impossible subgoals if misused8-- example (a b c : Nat) : a + b = a + c := by9-- congr -- Creates goal b = c, which may not be provable!congrArg and congrFun
lean
1-- Core Lean has congrArg and congrFun lemmas23-- congrArg: f a = f b from a = b4example (f : Nat → Nat) (a b : Nat) (h : a = b) : f a = f b :=5 congrArg f h67-- congrFun: f x = g x from f = g8example (f g : Nat → Nat) (h : f = g) (x : Nat) : f x = g x :=9 congrFun h x1011-- These are the building blocks congr usesReal-World Examples
Proving Map Equalities
lean
1import Mathlib.Tactic.Congr23-- Proving that mapped lists are equal4example (f : Nat → Nat) (xs ys : List Nat) (h : xs = ys) : 5 xs.map f = ys.map f := by6 congrArithmetic Expressions
lean
1import Mathlib.Tactic.Congr23-- Breaking down complex arithmetic4example (a b c : Nat) (h : a = b) : a * c + a = b * c + b := by5 congr 16 · congr 17 exact h8 · exact hInequalities with gcongr
lean
1import Mathlib.Tactic.GCongr23-- Monotonicity proofs4example (a b c : Nat) (hab : a ≤ b) (hc : c > 0) : a * c ≤ b * c := by5 gcongr67example (a b : Nat) (h : a ≤ b) : a + 5 ≤ b + 5 := by8 gcongrcongr vs simp
lean
1import Mathlib.Tactic.Congr23-- simp rewrites using lemmas4-- congr breaks down by structure56-- congr is useful when:7-- 1. You need to prove parts are equal separately8-- 2. simp doesn't know the relevant lemmas9-- 3. You want fine-grained control1011example (a b : Nat) (h : a = b) : [a, 1, 2] = [b, 1, 2] := by12 congr -- Immediately reduces to a = bCommon Patterns
lean
1import Mathlib.Tactic.Congr23-- Pattern: Prove outer structure matches, then inner4example (f g : Nat → Nat) (x y : Nat) 5 (hf : f = g) (hx : x = y) : f x = g y := by6 rw [hf, hx]78-- Alternative with congr9example (f : Nat → Nat) (x y : Nat) (h : x = y) : f x = f y := by10 congr1112-- Pattern: Focus on the differing part13example (a b c : Nat) (h : b = c) : a + b + 1 = a + c + 1 := by14 congr 2 -- Descend to b = c