rcases & obtain
Powerful pattern matching tactics for destructuring hypotheses.rcases and obtain extend the core cases tactic with recursive patterns.
❗
rcases and obtain require Mathlib. Add import Mathlib.Tactic.Cases orimport Mathlib.Tactic.Basic rcases
The rcases tactic ("recursive cases") extends the corecases tactic with a powerful pattern syntax. Instead of nested case splits, you write one pattern that destructures multiple layers at once.
lean
1import Mathlib.Tactic.Cases23-- rcases destructs with angle bracket patterns4example (h : ∃ n : Nat, n > 0) : True := by5 rcases h with ⟨n, hn⟩6 -- Now have n : Nat and hn : n > 07 trivial89-- Compare to cases:10example (h : ∃ n : Nat, n > 0) : True := by11 cases h with12 | intro n hn => trivialKey Takeaway
rcases h with ⟨x, y, z⟩ recursively destructsh, naming the parts x,y, z.Nested Patterns
The real power of rcases appears with nested structures. You can unpack existentials, conjunctions, and pairs all in a single pattern, avoiding multiple cases calls.
lean
1import Mathlib.Tactic.Cases23-- rcases handles nested structures in one step4example (h : ∃ n m : Nat, n < m ∧ m < 10) : True := by5 rcases h with ⟨n, m, hnm, hm10⟩6 -- n : Nat, m : Nat, hnm : n < m, hm10 : m < 107 trivial89-- Even deeper nesting10example (h : ∃ p : Nat × Nat, p.1 < p.2) : True := by11 rcases h with ⟨⟨a, b⟩, hab⟩12 -- a : Nat, b : Nat, hab : a < b13 trivialDisjunctions with |
lean
1import Mathlib.Tactic.Cases23-- Use | to split disjunctions4example (h : P ∨ Q) : Q ∨ P := by5 rcases h with hp | hq6 · right; exact hp7 · left; exact hq89-- Combined with existentials10example (h : (∃ n : Nat, n = 0) ∨ (∃ n : Nat, n > 0)) : True := by11 rcases h with ⟨n, hn⟩ | ⟨n, hn⟩12 all_goals trivialThe obtain Tactic
lean
1import Mathlib.Tactic.Obtain23-- obtain is like rcases but with a goal-style syntax4example (h : ∃ n : Nat, n > 0 ∧ n < 10) : True := by5 obtain ⟨n, hn_pos, hn_lt⟩ := h6 trivial78-- obtain can also introduce with a proof9example : ∃ n : Nat, n > 0 := by10 obtain ⟨n, hn⟩ : ∃ n : Nat, n > 0 := ⟨1, by norm_num⟩11 exact ⟨n, hn⟩💡
Use
obtain when you want to destructure and name parts in one step. Use rcases for pattern matching on existing hypotheses.Wildcard Patterns
lean
1import Mathlib.Tactic.Cases23-- Use _ to discard parts you don't need4example (h : ∃ n m : Nat, n < m) : ∃ n : Nat, True := by5 rcases h with ⟨n, _, _⟩6 exact ⟨n, trivial⟩78-- Use rfl pattern to substitute immediately9example (h : ∃ n : Nat, n = 5) : 5 = 5 := by10 rcases h with ⟨_, rfl⟩11 rflDeep Dive: rcases Patterns
The rcases pattern language:
⟨p₁, p₂, ...⟩— destruct products/existsp₁ | p₂— split on disjunctionsrfl— substitute equalities_— discard (anonymous)-— clear hypothesis after use@name— name for the whole match
The rfl Pattern
lean
1import Mathlib.Tactic.Cases23-- rfl immediately substitutes equalities4example (h : ∃ n : Nat, n = 3 ∧ n > 0) : 3 > 0 := by5 rcases h with ⟨_, rfl, h3⟩6 -- n is replaced by 3 everywhere7 exact h389-- Super useful for existentials with equations10example (h : ∃ x : Nat, x = 10 ∧ x * 2 = 20) : 10 * 2 = 20 := by11 rcases h with ⟨_, rfl, heq⟩12 exact heqReal-World Examples
Unpacking Complex Structures
lean
1import Mathlib.Tactic.Cases23-- Nested existentials with conditions4theorem unpack_bounds (h : ∃ ε > 0, ∀ x, |x| < ε → P x) : 5 ∃ δ : ℝ, δ > 0 := by6 rcases h with ⟨ε, hε_pos, _⟩7 exact ⟨ε, hε_pos⟩Case Analysis on Sum Types
lean
1import Mathlib.Tactic.Cases23-- Handling Either-like types4example (x : Sum Nat Bool) : Nat ∨ Bool := by5 rcases x with n | b6 · left; exact n7 · right; exact bWith obtain for Existence
lean
1import Mathlib.Tactic.Obtain23-- Proving existence by obtaining a witness4example : ∃ n : Nat, n^2 = 4 := by5 obtain ⟨n, hn⟩ : ∃ n : Nat, n = 2 := ⟨2, rfl⟩6 use n7 simp [hn]rcases vs cases vs match
lean
1import Mathlib.Tactic.Cases23-- Core Lean cases4example (h : P ∧ Q) : P := by5 cases h with6 | intro left right => exact left78-- rcases (Mathlib) - more concise9example (h : P ∧ Q) : P := by10 rcases h with ⟨hp, _⟩11 exact hp1213-- match in term mode14example (h : P ∧ Q) : P :=15 match h with16 | ⟨hp, _⟩ => hpExercise: Destruct an Existential
Use rcases to unpack an existential and use the witness.
lean
1import Mathlib.Tactic.Cases23example (h : ∃ n : Nat, n > 5) : ∃ m : Nat, m > 0 := by4 rcases h with ⟨n, hn⟩5 exact ⟨n, by omega⟩