Why This Matters
Lambda calculus is one of the two foundational models of computation (the other being Turing machines). It strips computation down to three operations: naming a variable, defining a function, and applying a function to an argument. Despite this simplicity, it can express any computable function.
Lambda calculus matters for three reasons. First, it is the theoretical foundation of functional programming (Haskell, ML, Lisp). Second, when you add types, it becomes the foundation of type theory and proof assistants like Lean and Coq. Third, the Curry-Howard correspondence says that typed lambda terms are proofs: programming and proving are the same activity in different notation.
Core Definitions
Lambda Term (Untyped)
The set of lambda terms is defined inductively:
- Variable: for any variable .
- Abstraction: if and is a variable, then . This denotes a function with parameter and body .
- Application: if , then . This denotes applying function to argument .
Nothing else is a lambda term. There are no numbers, no booleans, no data structures. Everything is built from these three forms.
Free and Bound Variables
In , the variable is bound. An occurrence of in that is not inside another is bound by this abstraction. A variable occurrence is free if it is not bound by any enclosing .
Example: in , is bound and is free.
Beta-Reduction
Beta-reduction is the computation rule of lambda calculus:
where means "substitute for every free occurrence of in " (with appropriate renaming to avoid variable capture). This is function application: apply the function to the argument by substituting for in the body .
Normal Form
A lambda term is in normal form if no beta-reduction can be applied to it or any of its subterms. A term in normal form is "fully computed." Not every lambda term has a normal form; for example, reduces to itself forever.
Alpha-Equivalence
Two terms are alpha-equivalent if they differ only by a consistent renaming of bound variables: provided does not occur free in . For example, . Lambda terms are formally identified up to alpha-equivalence; the choice of bound-variable name is irrelevant.
Eta-Reduction
Eta-reduction identifies a function with its pointwise application:
Eta says "if a function just hands its argument to , it is ." Beta-eta equivalence () is the standard equational theory of the lambda calculus and corresponds to extensional equality of functions.
Church Encodings
Lambda calculus has no built-in data types, but you can encode them as lambda terms.
Church booleans:
A boolean is a function that takes two arguments and returns one of them. Conditionals come for free: is just .
Church numerals:
A numeral is a function that takes and and applies to exactly times. Addition is . Multiplication is .
Recursion via Fixpoint Combinators
The untyped lambda calculus has no built-in recursion, yet it is Turing-complete. The trick is the Y combinator, due to Curry:
Applying to a function produces a fixed point of :
Verification: .
To define a recursive function such as factorial, write the body as a function of a "self" parameter and pass it to :
The Y combinator does not type-check in the simply typed lambda calculus (it relies on self-application ). This is why total functional languages (Coq, Agda) require the recursion principle of inductive types instead of an explicit fixpoint combinator. Other fixpoint combinators exist (Turing's is the call-by-value-friendly variant), but is canonical.
Reduction Strategies
Confluence guarantees that if a normal form exists, it is unique. But not every reduction strategy reaches it. Two are standard:
- Normal-order (leftmost-outermost): always reduce the leftmost outermost redex. If a normal form exists, normal-order reduction finds it. Corresponds to call-by-name evaluation in programming languages.
- Applicative-order (leftmost-innermost): always reduce arguments before applying functions. Corresponds to call-by-value. Faster in practice but may diverge when normal-order would terminate (e.g., has normal form under normal-order but loops under applicative-order).
Plotkin's "Call-by-name, call-by-value and the lambda-calculus" (Theoretical Computer Science 1975) gave the standard semantic comparison and introduced the call-by-value lambda calculus as a separate formal system. Real-world languages mix strategies: ML and OCaml are call-by-value, Haskell is call-by-need (lazy, a memoized form of call-by-name).
Main Theorems
Church-Rosser Theorem (Confluence)
Statement
If a lambda term reduces to both and (by possibly different sequences of beta-reductions), then there exists a term such that both and reduce to .
Intuition
It does not matter which reduction you perform first. All paths eventually converge. If a normal form exists, it is unique. This means that the "answer" a lambda term computes (if it terminates) does not depend on the evaluation strategy.
Proof Sketch
The standard proof uses the Tait-Martin-Lof method of parallel reductions. Define a relation (parallel reduction) that reduces all redexes simultaneously. Show that has the diamond property: if and , then there exists with and . Then is the transitive closure of , and the diamond property extends to the transitive closure.
Why It Matters
Confluence guarantees that lambda calculus is a well-defined computational model. The result of a computation does not depend on the order of evaluation. This is why pure functional programs are deterministic (in the absence of side effects) and why equational reasoning about programs is sound.
Failure Mode
Confluence holds for the full untyped pure lambda calculus, including terms with fixpoint combinators like and non-terminating terms such as . What fixpoint/recursion combinators break is strong normalization (the property that every reduction reaches a normal form), not confluence: has no normal form but it also has no diverging pair of reducts. Confluence is genuinely lost when you add non-deterministic features such as mutable state, I/O, or non-confluent rewrite rules. In simply typed and most other typed lambda calculi, both confluence and normalization hold.
The Church-Turing Thesis
Alonzo Church and Alan Turing independently defined computability in the 1930s: Church via lambda calculus, Turing via Turing machines. They proved that the two models compute exactly the same class of functions.
The Church-Turing thesis (not a theorem, but a widely accepted principle) states: every effectively computable function is computable by a Turing machine (equivalently, expressible in lambda calculus). No physically realizable computational model has been shown to exceed this boundary.
Simply Typed Lambda Calculus
The untyped lambda calculus allows self-application (), which leads to non-termination. The simply typed lambda calculus (STLC) restricts terms with types to guarantee termination.
Simple Types
Types are built from base types () using the function type constructor:
A term is a function taking inputs of type and producing outputs of type .
In STLC, every well-typed term has a normal form (strong normalization). Self-application is not typable, because would need type and type simultaneously, which requires , an infinite type.
The trade-off: STLC is not Turing-complete. It can only express total (terminating) functions. To recover full computational power, you add recursion (a fixpoint combinator), but then you lose guaranteed termination.
Curry-Howard Correspondence
The Curry-Howard correspondence is the observation that types correspond to propositions and terms correspond to proofs:
| Lambda calculus | Logic |
|---|---|
| Type | Proposition |
| Term of type | Proof that implies |
| Function application | Modus ponens |
| Lambda abstraction | Implication introduction |
A type is "inhabited" (has a term of that type) if and only if the corresponding proposition is provable. This correspondence is the foundation of proof assistants: to prove a theorem, you construct a term of the corresponding type.
Common Confusions
Lambda calculus is not about Greek letters
The is just notation for function definition. is the function that adds 1 to its input. In Python, this is lambda x: x + 1. The theoretical significance is that function definition is the only primitive; everything else is derived.
Not every lambda term terminates
beta-reduces to itself, looping forever. The untyped lambda calculus is Turing-complete, which means non-termination is possible. Simply typed lambda calculus guarantees termination but is weaker.
Exercises
Problem
Reduce the following lambda term to normal form: .
Problem
Write the Church encoding of the successor function , which takes a Church numeral and returns .
Problem
Explain why the self-application term cannot be typed in the simply typed lambda calculus.
References
Canonical:
- Barendregt, The Lambda Calculus: Its Syntax and Semantics (1984)
- Church, "An Unsolvable Problem of Elementary Number Theory" (1936)
- Plotkin, "Call-by-name, call-by-value and the lambda-calculus" (Theoretical Computer Science 1975) — call-by-name vs call-by-value semantics
- de Bruijn, "Lambda calculus notation with nameless dummies" (1972) — de Bruijn indices
Accessible:
- Pierce, Types and Programming Languages (2002), Chapters 5-9
- Hindley & Seldin, Lambda-Calculus and Combinators (2008)
- Selinger, Lecture Notes on the Lambda Calculus (2013) — open-access modern lecture notes
- Krivine, Lambda Calculus: Types and Models (1993)
Next Topics
- Dependent type theory: extending STLC so types can depend on values, enabling the Curry-Howard correspondence for full logic
- Proof theory and cut-elimination: the structure of proofs as computational objects