Lean 4 supports two styles of proof: tactic mode (interactive, goal-directed) and term mode (direct construction of a proof term). In term mode you write a Lean expression whose type is the proposition you want to prove — no tactics, no goal state. Understanding term-mode proofs gives you a deep insight into how Lean’s kernel works, and it is often the right choice for short, transparent proofs.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/leanprover/lean4/llms.txt
Use this file to discover all available pages before exploring further.
When to Use Term Mode vs Tactic Mode
| Situation | Prefer |
|---|---|
| Short, structural proof (one or two steps) | Term mode |
Simple equational reasoning (rfl, Eq.trans) | Term mode |
| Complex multi-step proof with many goals | Tactic mode |
Automation needed (omega, simp, grind) | Tactic mode |
| Proof readability for future readers | Either; calc bridges both |
| Performance-sensitive proof (large terms) | Tactic mode with have |
You can freely nest
by inside a term-mode proof to hand off any subgoal to tactic mode, and you can use term expressions inside tactic mode with exact. The two styles complement each other.Lambda Proofs of ∀
Because ∀ x : α, P x is literally a dependent function type (x : α) → P x, a proof of a universally-quantified proposition is just a function:
Anonymous Constructor Syntax ⟨a, b⟩
For any structure or inductive type with a single constructor, you can use angle brackets ⟨...⟩ as a shorthand. This is used constantly for And, Exists, Subtype, and custom structures.
Eq.subst and Eq.mpr
When you have a proof h : a = b and a proof ha : P a, you can obtain P b using Eq.subst:
Eq.mpr is the primitive used internally. Given h : P = Q (a proof that types are equal), Eq.mpr h : Q → P. This appears in desugared rewrites:
congrArg
congrArg f h lifts h : a = b through a function f, yielding f a = f b:
show — Type Annotation in Proofs
show t in a term-mode context is @id t, which forces Lean to unify the expected type with t. It is helpful for readability when the inferred type is not obvious:
have and let in Term Mode
have binds a local proof term; let binds a local definition that may appear in subsequent types.
suffices in Term Mode
suffices h : t from e introduces an intermediate goal t. You then provide e : original_goal which may refer to h : t, followed by a proof of t.
calc Blocks
calc is ideal for chains of equalities, inequalities, or any transitive relation. It is the clearest way to present multi-step equational proofs in either term or tactic mode.
match in Proofs
match on a proof of an inductive proposition is the primitive behind cases and obtain. It is fully available in term-mode proofs.
Combining Term Mode and Tactic Mode
You can freely switch between the two styles. The most common pattern is a term-mode skeleton withby leaves:
by block with exact to hand off to term mode — is equally natural:
A Self-Contained Term-Mode Proof
Here is a complete proof of function composition, written entirely in term mode:have and calc:
The Lean 4 Kernel
The Lean 4 Kernel
Every proof term in Lean 4 — whether produced by tactics or written directly — is ultimately checked by the kernel: a small, trusted elaborator that verifies type correctness. Tactics are macros that generate kernel-checkable proof terms. This means:
- A
by omegaproof compiles to a proof term the kernel can verify without trusting the omega solver itself (in kernel mode). native_decideis a partial exception: it trusts the native compiler rather than the kernel.- You can see the actual proof term with
#print myTheoremorset_option pp.all true.