Structural tactics shape the architecture of a proof: they introduce hypotheses, break compound goals into pieces, provide witnesses for existentials, apply lemmas, and handle classical reasoning. While arithmetic and simplification tactics close goals automatically, structural tactics put you in control of the proof’s logical flow. Every Lean 4 proof writer needs a solid command ofDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/leanprover-community/mathlib4/llms.txt
Use this file to discover all available pages before exploring further.
apply, exact, refine, obtain, rcases, induction, and ext, as well as the more specialized tools like wlog and tfae_have.
apply and exact
apply closes a goal by applying a term whose conclusion matches the goal, generating subgoals for any premises. exact closes a goal completely with a proof term that matches it precisely — it admits no remaining subgoals.
refine
refine is a more flexible version of exact that allows placeholders (_ or ?name) for parts of the term you want to fill in later. It is useful for building up a proof term incrementally.
constructor
constructor splits a goal that is a conjunction (∧), an iff (↔), an existential (∃), or any inductive type with exactly one constructor, into its component goals.
ext
ext applies extensionality lemmas tagged with @[ext] to reduce equality of structured objects to equality of their components. It is used for functions (via funext), sets (via Set.ext), finsets, bundled morphisms, and many other types.
use
use provides witnesses for existential goals (∃ x, P x) and the first component of conjunctive goals. After use t, the goal ∃ x, P x becomes P t.
obtain and rcases
obtain and rcases destructure hypotheses by pattern matching. They are the tactic-mode equivalents of match and fun ⟨a, b⟩ => in term mode. Use them to extract components from conjunctions, existentials, disjunctions, and inductive types.
- obtain
- rcases
cases and induction
cases performs case analysis on an inductive type, natural number, boolean, or hypothesis. induction performs structural induction and additionally provides an inductive hypothesis.
For simple induction on
ℕ where the goal is arithmetic, omega or linarith can often finish the step without explicitly writing out the induction. For complex recursive structures, induction with explicit case names is clearer.by_contra and by_cases
by_contra h introduces the negation of the current goal as hypothesis h and switches the goal to False, enabling proof by contradiction. by_cases h : P performs classical case analysis on any proposition P, splitting into cases P and ¬P.
contrapose
contrapose replaces a goal P → Q (or P given ¬Q in context) with its contrapositive ¬Q → ¬P. Combined with push_neg, this is a standard pattern for proving implications.
push_neg
push_neg pushes negations inward through quantifiers and logical connectives. It is fully covered in the Simplification Tactics page and is often used together with by_contra or contrapose.
wlog
wlog reduces the goal to a canonical case. wlog h : P splits into two goals: a side goal (placed first) where you reduce the h : ¬ P case to the P case using symmetry, and a main goal where h : P is in context and you prove the goal directly. The side goal also receives this, the statement that the main goal holds whenever P holds.
wlog syntax and usage patterns
wlog syntax and usage patterns
The general form is:After
wlog h : P, two goals are produced:- Side goal (first): the context gains
h : ¬ Pandthis(orH), the statement that the original goal follows fromP. You must reduce the general case to the case wherePholds, typically by a symmetry argument applyingthiswith swapped arguments. - Main goal: the context gains
h : Pand you prove the original goal under this assumption.
generalizing x y modifier reverts x and y before constructing the side goal, so the wlog-claim this can be applied to x and y in a different order (the typical symmetry use case).This is most useful for symmetric goals (like swapping two variables) or for goals where one case implies the other by a simple transformation.tfae_have and tfae_finish
tfae_have and tfae_finish prove goals of the form TFAE [P₁, P₂, ..., Pₙ] (“The Following Are Equivalent”). You establish individual implications using tfae_have i → j and then call tfae_finish to assemble them into the full equivalence.
TFAE requires a Hamiltonian path through the implication graph — you need enough tfae_have statements for tfae_finish to find a cycle visiting all propositions. For n propositions, n directed implications suffice if they form a cycle (1→2→3→…→n→1).Quick Comparison
Goal Decomposition
constructor — split conjunctions/iffs into partscases — case-split on an inductive typercases / obtain — pattern-match a hypothesisext — reduce equality of structures to componentsWitness Provision
use — provide a witness for an existentialrefine — partially fill a proof term with _apply — apply a lemma, generate subgoalsexact — close goal with a complete proof termClassical Reasoning
by_contra — proof by contradictionby_cases — classical case split on any Propcontrapose — switch to contrapositivepush_neg — push negations inwardAdvanced Structure
induction — structural inductionwlog — reduce to canonical casetfae_have / tfae_finish — equivalence chainsobtain — simultaneous destructuring