ext & funext
Apply extensionality principles to prove equality.ext proves two things equal by showing their components or behaviors are equal.
❗
ext in its full power requires Mathlib. The basic funext is available in core Lean 4.Function Extensionality
lean
1-- Two functions are equal if they give equal outputs for all inputs2-- This is funext, available in core Lean34example : (fun x : Nat => x + 0) = (fun x => x) := by5 funext x6 -- Goal: x + 0 = x7 simp89example : (fun x : Nat => x * 1) = (fun x => x) := by10 funext x11 ringKey Takeaway
funext x transforms a goalf = g into proving f x = g xfor an arbitrary x.The ext Tactic
lean
1import Mathlib.Tactic.Ext23-- ext is more powerful - works for any type with @[ext] lemmas4example : (fun x : Nat => x + 0) = (fun x => x) := by5 ext x6 simp78-- ext works on structures too9example (p q : Nat × Nat) (h1 : p.1 = q.1) (h2 : p.2 = q.2) : p = q := by10 ext11 · exact h1 -- First component12 · exact h2 -- Second componentSet Extensionality
lean
1import Mathlib.Tactic.Ext2import Mathlib.Data.Set.Basic34-- Two sets are equal if they have the same elements5example (A B : Set Nat) (h : ∀ x, x ∈ A ↔ x ∈ B) : A = B := by6 ext x7 exact h x89-- Proving set equalities10example : ({1, 2} : Set Nat) = {2, 1} := by11 ext x12 simp [Set.mem_insert_iff]13 tautoStructure Extensionality
lean
1import Mathlib.Tactic.Ext23-- Structures are equal if all fields are equal4structure Point where5 x : Float6 y : Float78-- @[ext] generates an extensionality lemma9@[ext]10theorem Point.ext_iff (p q : Point) : p = q ↔ p.x = q.x ∧ p.y = q.y := by11 constructor12 · intro h; simp [h]13 · intro ⟨hx, hy⟩; cases p; cases q; simp_all1415example (p q : Point) (hx : p.x = q.x) (hy : p.y = q.y) : p = q := by16 ext17 · exact hx18 · exact hyℹ
Mark your structures with
@[ext] to automatically generate extensionality lemmas that extcan use.Multiple Variables
lean
1import Mathlib.Tactic.Ext23-- ext can introduce multiple variables4example : (fun x y : Nat => x + y) = (fun x y => y + x) := by5 ext x y6 ring78-- Or one at a time9example : (fun x y : Nat => x + y) = (fun x y => y + x) := by10 ext x11 ext y12 ringDeep Dive: How ext Works
ext looks for lemmas tagged with@[ext] that match the goal type:
lean
1-- For functions: funext2-- For sets: Set.ext3-- For products: Prod.ext4-- For structures: generated by @[ext]56-- The lemma should have the form:7-- (∀ components are equal) → whole is equalext with Patterns
lean
1import Mathlib.Tactic.Ext23-- You can name and pattern-match the introduced variable4example : (fun p : Nat × Nat => p.1 + p.2) = (fun p => p.2 + p.1) := by5 ext ⟨a, b⟩6 ring78-- Or use wildcards9example : (fun _ : Nat => 0) = (fun _ => 0) := by10 ext _11 rflReal-World Examples
Proving Function Compositions Equal
lean
1import Mathlib.Tactic.Ext23-- (f ∘ id) = f4example (f : Nat → Nat) : (fun x => f (id x)) = f := by5 ext x6 rfl78-- (id ∘ f) = f9example (f : Nat → Nat) : (fun x => id (f x)) = f := by10 ext x11 rflSet Algebra
lean
1import Mathlib.Tactic.Ext2import Mathlib.Data.Set.Basic34-- A ∩ B = B ∩ A5example (A B : Set α) : A ∩ B = B ∩ A := by6 ext x7 constructor8 · intro ⟨ha, hb⟩; exact ⟨hb, ha⟩9 · intro ⟨hb, ha⟩; exact ⟨ha, hb⟩Vector Space Operations
lean
1import Mathlib.Tactic.Ext23-- Prove two linear maps are equal4-- (Would need more imports for real linear maps)5example (f g : Nat → Nat) (h : ∀ n, f n = g n) : f = g := by6 ext n7 exact h next vs funext
lean
1-- funext: core Lean, functions only2example : (fun x : Nat => x) = (fun x => x) := by3 funext x4 rfl56-- ext: Mathlib, works on more types7-- - Functions (uses funext)8-- - Sets (uses Set.ext)9-- - Structures (uses generated lemmas)10-- - Products, subtypes, etc.1112-- Prefer ext when available for its generality