Simple calculations with the Church $\lambda$-calculus
Three grammar rules, one reduction rule — and a Turing-complete language in which numbers, booleans and recursion are derived, not assumed.
dr Bartosz Naskręcki · Adam Mickiewicz University in Poznań · CCAI, Warsaw Univ. of Technology
▷ live lab: /lab-lambda
Why this matters
A proof assistant is, at bottom, a machine that checks that a term has a type. Before types and before proofs-as-programs there is the raw computational engine: terms that reduce.
a computation is a chain of reductions;
"the answer" is a normal form;
that the answer is well-defined at all is a theorem (Church–Rosser).
When Lean evaluates #reduce or accepts a proof by rfl, it runs a typed, terminating descendant of the machine we build today.
Where we are going
Foundations
syntax, binding, $\alpha$-equivalence
capture-avoiding substitution
$\beta$ / $\eta$ and normal forms
Church–Rosser confluence
Computing
booleans, conditionals, pairs
numerals and arithmetic
the notorious predecessor
the $Y$-combinator & undecidability
Every calculation is reproducible in the Lambda Lab; the capstones are cross-checked in four provers.
$\mathrm{FV}(\lambda x.\,t) = \mathrm{FV}(t)\setminus\{x\}$; a closed term is a combinator.
Bound names carry no meaning: $\lambda x.\,x \equiv_\alpha \lambda y.\,y$. From now on we compute on $\alpha$-equivalence classes.
▷ alpha \x. x = \y. y ▷ debruijn \x. x (\x. x) — strict α-check, and the nameless de Bruijn view under which shadowing in $\lambda x.\,x\,(\lambda x.\,x)$ simply disappears.
Misreading the conventions silently changes the term — a leading cause of student errors.
The capture trap. $(\lambda y.\,x)[x:=y]$ is not $\lambda y.\,y$ (identity). Rename first: $\lambda y'.\,y$ — a constant function returning the still-free $y$.
Barendregt's variable convention lets us pick bound names distinct from all free ones — a bookkeeping shortcut, not a licence to ignore capture.
reduce (\x. \y. x) y
One $\beta$-step forces the capture-trap substitution from the box above — watch the engine rename $\lambda y$ to a fresh binder before substituting.
$\beta$-reduction, $\eta$, normal forms
The sole computation rule contracts a redex $(\lambda x.\,t)\,u$:
$$ (\lambda x.\,t)\,u \;\to_\beta\; t[x := u]. $$
A term with no redex is a $\beta$-normal form. $\eta$ adds extensionality: $\lambda x.\,(t\,x) \to_\eta t$ when $x\notin\mathrm{FV}(t)$.
Not every term terminates. The paradigm of divergence reduces to itself:
By default the Lab's reduce/nf stay $\beta$-only — they will not collapse $\lambda x.\,f\,x$ to $f$. Opt in with eta:
eta \x. f x
Strategy is not cosmetic
With more than one redex, the choice can decide termination. Consider $(\lambda x.\,y)\,\Omega$:
Normal order
leftmost-outermost (lazy)
$(\lambda x.\,y)\,\Omega \to_\beta y$ — done in one step, the argument discarded.
Applicative order
leftmost-innermost (eager)
insist on reducing $\Omega$ first — and loop forever.
Same term, opposite fate. This is why the Lab uses normal order.
Confluence & Church–Rosser
Why is "the normal form" well-defined despite arbitrary choices? Because reduction is confluent.
Church–Rosser (1936). If $M \twoheadrightarrow P$ and $M \twoheadrightarrow Q$, then some $S$ has $P \twoheadrightarrow S$ and $Q \twoheadrightarrow S$.
Uniqueness: every term has at most one $\beta$-normal form (up to $\alpha$).
Consistency: $K = \lambda x\,y.\,x$ and $I = \lambda x.\,x$ are distinct normal forms, so $K \neq_\beta I$.
Standardization: if a normal form exists, normal order reaches it — the complete strategy.
Confluent yet not strongly normalizing: $\Omega$ diverges. The two properties are independent.
Church booleans & pairs
Guiding idea: data as its own eliminator. A boolean is a chooser:
All of it is $f^{m}\circ f^{n} = f^{m+n}$ and $(f^{n})^{m} = f^{nm}$ in disguise. Note $\mathtt{false}$ and $\overline{0}$ are the same term. The $\eta$-long pow makes $\mathtt{pow}\,\overline m\,\overline 0 = \overline 1$ on the nose — the bare $\lambda m\,n.\,n\,m$ stops at $\lambda x.\,x$, only $\eta$-equal to $\overline 1$.
The same encoding, checked by Lean's kernel
def Church := (α : Type) → (α → α) → α → α
def czero : Church := fun _ _ x => x
def csucc (n : Church) : Church := fun α f x => f (n α f x)
def cplus (m n : Church) : Church := fun α f x => m α f (n α f x)
def toNat (n : Church) : Nat := n Nat (· + 1) 0
-- 2 + 3 = 5, verified by the kernel:
example : toNat (cplus (csucc (csucc czero))
(csucc (csucc (csucc czero)))) = 5 := rfl
The Church numeral is a polymorphic type that computes by rfl. The proof is the program.
The predecessor — the hard case
Church believed it undefinable, until Kleene's "wisdom-teeth trick." Iterate the map $(a,b)\mapsto(b,\,b{+}1)$ from $(0,0)$: after $n$ steps the pair is $(n{-}1,\,n)$, read off the first component.
Meta-level payoff. $\lambda$-definable $=$ general recursive $=$ Turing-computable (Church–Turing). And $\beta$-convertibility is undecidable (Church 1936).
An untyped $Y$ has no home in a total type theory — which is exactly why Lean rejects def Y (f : α → α) : α := f (Y f) and offers Nat.rec instead.
Run it yourself
Open the Lambda Lab and type:
reduce AND TRUE FALSE
nf PLUS 2 3
nf PRED 3
reduce OMEGA
let MYNOT = \p. p FALSE TRUE
nf MYNOT TRUE
equiv PLUS 2 3 = 5
tour
Every calculation in this lecture is reproducible in the browser; let builds your own encodings, equiv decides $=_\beta$ on terms that normalize, and tour runs a 60-second guided version.
Recap & references
Three formers, one $\beta$-rule — a Turing-complete engine.
Substitution avoids capture; $\alpha$ $\neq$ $\beta$; not everything terminates ($\Omega$).
Church–Rosser makes normal forms unique; normal order is complete.
Booleans, numerals, arithmetic, pred and $Y$ are all derived.
Barendregt, Introduction to Lambda Calculus · Selinger, Lecture Notes · Pierce, TAPL ch. 5 · Church (1936) · the course book at /vietnam2026/book