One law, three readings
Here are three facts from three different subjects.
- Programming. A function of two arguments is the same thing as a function that takes the first argument and returns a function of the second. Every functional programmer meets this as currying.
- Logic. From hypotheses and you can prove exactly when from alone you can prove . This is the deduction theorem.
- Sets. Maps correspond bijectively to maps , where is the set of all functions .
They are one fact:
The functor has a right adjoint . Read in a category of types and programs, this is currying. Read in a poset of propositions ordered by provability, it is the deduction theorem . Read in , it is the exponential law. Categorical logic studies this coincidence systematically. Connectives and quantifiers are characterised by universal properties, a logic is interpreted in any category that has the matching structure, and proofs become morphisms. William Lawvere's slogan from 1969 is that the logical operations are adjoint functors.
Two payoffs make the subject worth learning. First, a single definition (soundness in a category with structure) gives at once the set-theoretic semantics, the topological semantics, Kripke semantics, sheaf semantics and the semantics of programs. Second, the categorical view explains which logical laws hold and why. Excluded middle, for instance, is not a law of every reasonable logic. It is a special property of Boolean models, and it fails in the open sets of the real line.
The dictionary
The Curry–Howard–Lambek correspondence lines up three languages:
| Logic | Type theory | Category |
|---|---|---|
| proposition | type | object |
| proof of from | term | morphism |
| cut, substituting a proof | substitution | composition |
| truth | unit type | terminal object |
| conjunction | product type | product |
| implication | function type | exponential |
| falsity , disjunction | empty type, sum type | initial object, coproduct |
| proof simplification | β-reduction | equations between morphisms |
| , | -, -types | left and right adjoints to pullback |
Two ways of forgetting will matter. If you remember only whether is provable from and forget which proof, the category becomes a preorder. Identify interderivable propositions and you get a poset. In a poset, products are meets, coproducts are joins and exponentials are implications, so a cartesian closed poset with finite joins is exactly a Heyting algebra. If instead you keep the proofs, you get a genuine category in which different proofs of the same statement are different arrows, and β-reduction says when two proofs are "the same".
Definitions
Throughout, the learner is assumed to know adjunctions, products and terminal objects and the basics of type theory and propositions as types.
Definition— cartesian closed category
A category is cartesian closed (a CCC) if it has a terminal object , binary products , and for every object the functor has a right adjoint . Equivalently, for all there are an object and a morphism such that for every there is a unique with .
Definition— Heyting algebra
A Heyting algebra is a lattice with a least element and a greatest element , together with a binary operation such that for all :
The pseudo-complement is , the largest element whose meet with is . A Heyting algebra is Boolean if for all (equivalently, for all ).
In categorical terms, a Heyting algebra is a poset that is cartesian closed (finite meets and implications) and has finite coproducts (finite joins). The defining law says precisely that .
Definition— simply typed λ-calculus with products
Types are generated by a base type , the unit type , products and function types . A context is a list . Terms are typed by the rules
βη-equality is the least congruence containing
Definition— interpretation in a CCC
Fix a CCC and an object . Extend to all types by , and , and to contexts by . A term is interpreted as a morphism , by induction on :
- a variable is the -th product projection;
- is the unique map to ; ; ;
- , the curried form of ;
- .
Definition— quantifiers along a map
For a map of sets, substitution (pulling back) is , . Define
For the projection these are and : quantifying out the variable .
Examples and non-examples
Example— Cartesian closed categories
- , with the set of functions (proved below). Also , which shows that a CCC need not have infinite limits.
- (small categories), with the functor category.
- Every presheaf category . This is part of the reason presheaf categories are toposes.
- Every Heyting algebra, viewed as a poset category. In particular every Boolean algebra, with , and every finite chain , with if and otherwise.
Example— Non-examples
- is not cartesian closed. In any CCC with an initial object , the functor is a left adjoint, so it preserves the initial object: . In the trivial group is initial, but . If were cartesian closed, every group would be trivial.
- is not cartesian closed. The functor does not preserve all quotient maps, so it has no right adjoint. The exponentiable spaces are exactly the core-compact ones (Day and Kelly, 1970), for example the locally compact Hausdorff spaces. Algebraic topologists therefore work in a convenient subcategory such as compactly generated spaces.
- as a poset category has products () and exponentials would be implications, but it has no top element, so no terminal object. It is not cartesian closed. Adjoining a top element repairs this.
Example— Open sets of the line
For any topological space , the open sets form a Heyting algebra under inclusion, with
the largest open set whose intersection with lies in . (Meets are intersections and joins are unions. The residuation law holds because iff , as is open, iff .) In :
- for : , so , and ;
- for : , so .
Excluded middle and double-negation elimination both fail, and the failure sits at a single boundary point. Truth values in are "true on an open region". An open region and its pseudo-complement can leave a boundary on which neither is true.
Example— Interpreting a term
The term is interpreted in any CCC as , where discards the empty part of the context. It is the symmetry isomorphism of the product. The closed term of type is interpreted in as currying itself. Under Curry–Howard it is a proof of .
Example— Quantifiers as shadows
Let and . Then , the shadow of on the -axis, and , the set of whose entire vertical line lies in . Existential quantification is a direct image (a projection). Universal quantification is its dual.
The central theorems
Theorem— Theorem 1 (Set is cartesian closed)
For sets , let be the set of functions and . For every there is a unique with .
Proof
Existence. Put . Then .
Uniqueness. If , then for all , so by extensionality of functions, for all . With the terminal object and the cartesian product, is cartesian closed.
∎
A useful consequence of the universal property in any CCC is the naturality of currying: for ,
because both sides satisfy , and the map with that property is unique.
Theorem— Theorem 2 (soundness of the interpretation)
Let be a CCC with an object . If is derivable by βη-equality, then .
Proof
Two lemmas, both by induction on terms.
Weakening. If is a term in context and is the same term regarded in context , then , where . Variables are projections, and projections compose to projections. The case uses naturality of currying.
Substitution. If and , then
More generally, a simultaneous substitution from to is interpreted as the tuple of the interpretations of the substituted terms, and . For variables this is the definition of a tuple, and the pairing, projection and application cases follow from . For , the substitution under the binder is weakened and extended by , interpreted as by the weakening lemma. Then naturality of currying gives .
The equations. The interpretation is defined compositionally, so it respects the congruence rules, reflexivity, symmetry and transitivity. It remains to check the axioms.
- Products: and hold by the universal property of the product. Any two maps into are equal.
- β for functions:
- η for functions: by weakening, , by uniqueness in the universal property.
∎
Theorem 2 has a converse. Make a category whose objects are types and whose morphisms are βη-classes of terms . This syntactic category is itself cartesian closed: it is the free CCC on the base types. So an equation between terms holds in every CCC exactly when it is βη-derivable. This is the precise content of the Curry–Howard–Lambek correspondence. Lambek and Scott (1986, Part I) give the proof and the equivalence between λ-theories and cartesian closed categories that it extends to. For the single model , Friedman (1975) proved that equality in the full set-theoretic model over an infinite base set coincides with βη-equality for the simply typed λ-calculus. The computation section shows why finite base sets are not enough.
Theorem— Theorem 3 (Lawvere: quantifiers are adjoints)
For every , as monotone maps between the posets and ,
Proof
() If and , then , so . Conversely, if and with , then .
() Suppose and . Any with lies in , so . Conversely, suppose and . Then , and itself lies over , so .
∎
Since right adjoints preserve limits (here, meets) and left adjoints preserve colimits (joins), Theorem 3 explains familiar quantifier laws and their failures:
while need not distribute over and need not distribute over . The same adjunctions make sense in any category with pullbacks and a poset of "predicates" (subobjects) on each object. This is Lawvere's notion of a hyperdoctrine. Two compatibility conditions are needed there. Frobenius reciprocity says ; it is a one-line check in , done in Lean below. Beck–Chevalley says that quantification commutes with substitution along pullback squares; in syntax, . Even equality is an adjoint. For the diagonal , the predicate is the equality relation (Lawvere 1970).
Theorem— Theorem 4 (soundness for Heyting algebras)
Let be a Heyting algebra and an assignment of elements of to propositional variables, extended to formulas by , , , and . If is derivable from hypotheses in intuitionistic natural deduction, then .
Proof
First, a Heyting algebra is a distributive lattice. The map is a left adjoint (of ), so it preserves joins: .
Now induct on the derivation, writing . A hypothesis satisfies . The rules for , and the -introductions are the universal properties of top, meet and join, and -elimination is .
- -introduction: from the residuation law gives .
- -elimination: from and we get , the counit of the adjunction.
- -elimination: from , and we get , by distributivity.
∎
Theorem— Theorem 5 (completeness: the Lindenbaum–Tarski algebra)
If in every Heyting algebra under every valuation, then is derivable in intuitionistic propositional logic.
Proof
Let be the set of formulas modulo interderivability ( iff and ), ordered by iff . The rules show that the connectives are well defined on classes, that is the meet, the join (-introduction gives the upper bounds and -elimination gives leastness), the top and the bottom. Finally, iff by -introduction and -elimination, so is the Heyting implication. Thus is a Heyting algebra (the Lindenbaum–Tarski algebra). With the valuation , induction on formulas gives . If is valid in all Heyting algebras, then , so and hence .
∎
Theorem— Theorem 6 (excluded middle is not derivable, but its double negation is)
in intuitionistic propositional logic, while .
Proof
If , Theorem 4 would give for every open . This fails for , as computed above. Here is a proof that needs no computation of . In any Heyting algebra . If also , then and are disjoint open sets covering , so is open and closed. Since is connected, is or , which is false.
A derivation of : assume . Under the further assumption , the formula follows by -introduction, and yields . Discharging gives , hence again by -introduction, and yields . Discharging gives .
∎
The same argument shows that is not derivable either: in the two-element Boolean algebra it evaluates to . Intuitionistic logic does not deny excluded middle. It declines to assume it, and it proves that excluded middle can never be refuted. Glivenko's theorem (1929) sharpens this: a propositional formula is a classical tautology if and only if is intuitionistically derivable.
Formalisation in Lean
The Lean module Lumenary.CategoricalLogic formalises three pieces of this lesson, mostly from scratch, using Mathlib for lattices, topology and the category of types.
The λ-calculus and its semantics. Terms are intrinsically typed: Tm Γ A contains only well-typed terms, so the typing rules are built into the constructors. Variables are typed de Bruijn indices, which makes substitution capture-avoiding by construction. Lean contexts grow at the front (A :: Γ denotes ⟦A⟧ × ⟦Γ⟧), the mirror image of the convention in the human proof. That is only bookkeeping.
/-- **Terms** of the simply typed λ-calculus with unit and products, typed *intrinsically*:
`Tm Γ A` contains exactly the well-typed terms of type `A` in context `Γ`. Read through
Curry–Howard, `Tm Γ A` is the set of natural-deduction proofs of `A` from hypotheses `Γ` in the
`⊤, ∧, →` fragment of intuitionistic logic. -/
inductive Tm : List Ty → Ty → Type where
| var {Γ : List Ty} {A : Ty} : Var Γ A → Tm Γ A
| star {Γ : List Ty} : Tm Γ .unit
| pair {Γ : List Ty} {A B : Ty} : Tm Γ A → Tm Γ B → Tm Γ (.prod A B)
| fst {Γ : List Ty} {A B : Ty} : Tm Γ (.prod A B) → Tm Γ A
| snd {Γ : List Ty} {A B : Ty} : Tm Γ (.prod A B) → Tm Γ B
| lam {Γ : List Ty} {A B : Ty} : Tm (A :: Γ) B → Tm Γ (.arr A B)
| app {Γ : List Ty} {A B : Ty} : Tm Γ (.arr A B) → Tm Γ A → Tm Γ B/-- **βη-conversion**: the equational theory of the simply typed λ-calculus with products.
It is the least congruence containing the β-rules (`fst ⟨s, t⟩ = s`, `snd ⟨s, t⟩ = t`,
`(λx. t) u = t[u/x]`) and the η-rules (`⟨fst p, snd p⟩ = p`, `t = ⋆` at unit type,
`λx. f x = f` with `x` not free in `f`). These are exactly the equations of a cartesian closed
category, read through the term ↔ morphism dictionary. -/
inductive Conv : {Γ : List Ty} → {A : Ty} → Tm Γ A → Tm Γ A → Prop where
| refl {Γ : List Ty} {A : Ty} (t : Tm Γ A) : Conv t t
| symm {Γ : List Ty} {A : Ty} {s t : Tm Γ A} : Conv s t → Conv t s
| trans {Γ : List Ty} {A : Ty} {s t u : Tm Γ A} : Conv s t → Conv t u → Conv s u
| pair {Γ : List Ty} {A B : Ty} {s s' : Tm Γ A} {t t' : Tm Γ B} :
Conv s s' → Conv t t' → Conv (.pair s t) (.pair s' t')
| fst {Γ : List Ty} {A B : Ty} {p p' : Tm Γ (.prod A B)} : Conv p p' → Conv (.fst p) (.fst p')
| snd {Γ : List Ty} {A B : Ty} {p p' : Tm Γ (.prod A B)} : Conv p p' → Conv (.snd p) (.snd p')
| lam {Γ : List Ty} {A B : Ty} {t t' : Tm (A :: Γ) B} : Conv t t' → Conv (.lam t) (.lam t')
| app {Γ : List Ty} {A B : Ty} {s s' : Tm Γ (.arr A B)} {t t' : Tm Γ A} :
Conv s s' → Conv t t' → Conv (.app s t) (.app s' t')
| beta_fst {Γ : List Ty} {A B : Ty} (s : Tm Γ A) (t : Tm Γ B) : Conv (.fst (.pair s t)) s
| beta_snd {Γ : List Ty} {A B : Ty} (s : Tm Γ A) (t : Tm Γ B) : Conv (.snd (.pair s t)) t
| beta_arr {Γ : List Ty} {A B : Ty} (t : Tm (A :: Γ) B) (u : Tm Γ A) :
Conv (.app (.lam t) u) (t.subst (single u))
| eta_prod {Γ : List Ty} {A B : Ty} (p : Tm Γ (.prod A B)) : Conv (.pair (.fst p) (.snd p)) p
| eta_unit {Γ : List Ty} (t : Tm Γ .unit) : Conv t .star
| eta_arr {Γ : List Ty} {A B : Ty} (f : Tm Γ (.arr A B)) :
Conv (.lam (.app (f.rename Var.succ) (.var .zero))) fThe interpretation lands in Lean's types and functions, the type-theoretic stand-in for . lam is currying and app is evaluation, exactly as in the definition above:
/-- **The interpretation of terms as morphisms** `⟦Γ⟧ → ⟦A⟧` of the cartesian closed category
of types: pairing is the map into a product, `fst`/`snd` compose with projections, `lam` is
**currying** (the bijection `Hom(Γ × A, B) ≅ Hom(Γ, B^A)`), and `app` composes with
**evaluation** `B^A × A → B`. -/
def Tm.denote {X : Type} : {Γ : List Ty} → {A : Ty} → Tm Γ A → ctxDenote X Γ → A.denote X
| _, _, .var v, γ => v.denote γ
| _, _, .star, _ => ()
| _, _, .pair s t, γ => (s.denote γ, t.denote γ)
| _, _, .fst t, γ => (t.denote γ).1
| _, _, .snd t, γ => (t.denote γ).2
| _, _, .lam t, γ => fun a => t.denote (a, γ)
| _, _, .app s t, γ => s.denote γ (t.denote γ)The substitution lemma is the "logical relation" form of the human lemma . Instead of building the tuple , it assumes that each substituted term denotes the value of the variable it replaces. The soundness theorem then follows the human proof case by case:
/-- **Substitution lemma** — the semantic heart of Curry–Howard–Lambek: substituting terms for
variables is interpreted by *composition* with the tuple of their interpretations. Precisely,
if every `σ v` denotes (at `δ`) the value of `v` (at `γ`), then `t.subst σ` denotes (at `δ`) the
value of `t` (at `γ`). The `lam` case needs the renaming lemma for the weakening in
`substExt`. -/
theorem denote_subst {X : Type} {Γ Δ : List Ty} {A : Ty} (t : Tm Γ A)
(σ : ∀ {B : Ty}, Var Γ B → Tm Δ B) (δ : ctxDenote X Δ) (γ : ctxDenote X Γ)
(h : ∀ {B : Ty} (v : Var Γ B), (σ v).denote δ = v.denote γ) :
(t.subst σ).denote δ = t.denote γ := by
induction t generalizing Δ with
| var v => exact h v
| star => rfl
| pair s t ihs iht => exact congrArg₂ Prod.mk (ihs σ δ γ h) (iht σ δ γ h)
| fst t ih => simp only [Tm.subst, Tm.denote, ih σ δ γ h]
| snd t ih => simp only [Tm.subst, Tm.denote, ih σ δ γ h]
| lam t ih =>
funext a
apply ih (substExt σ) (a, δ) (a, γ)
intro B v
cases v with
| zero => rfl
| succ v =>
show ((σ v).rename Var.succ).denote (a, δ) = v.denote γ
rw [denote_rename (σ v) Var.succ (a, δ) δ (fun _ => rfl)]
exact h v
| app s t ihs iht => simp only [Tm.subst, Tm.denote, ihs σ δ γ h, iht σ δ γ h]/-- **Soundness of the interpretation** (Lambek): βη-convertible terms denote the *same*
morphism `⟦Γ⟧ → ⟦A⟧`, for every interpretation `X` of the base type. Proved by induction on
the derivation of convertibility; the congruence rules use function extensionality, β for
functions is `beta_sound`, and η for functions is the renaming lemma. -/
theorem Conv.sound {X : Type} {Γ : List Ty} {A : Ty} {s t : Tm Γ A} (h : Conv s t) :
(s.denote : ctxDenote X Γ → A.denote X) = t.denote := by
induction h with
| refl t => rfl
| symm _ ih => exact ih.symm
| trans _ _ ih₁ ih₂ => exact ih₁.trans ih₂
| pair _ _ ih₁ ih₂ => funext γ; exact congrArg₂ Prod.mk (congrFun ih₁ γ) (congrFun ih₂ γ)
| fst _ ih => funext γ; simp only [Tm.denote, ih]
| snd _ ih => funext γ; simp only [Tm.denote, ih]
| lam _ ih => funext γ a; exact congrFun ih (a, γ)
| app _ _ ih₁ ih₂ => funext γ; simp only [Tm.denote, ih₁, ih₂]
| beta_fst s t => rfl
| beta_snd s t => rfl
| beta_arr t u => funext γ; exact beta_sound t u γ
| eta_prod p => rfl
| eta_unit t => rfl
| eta_arr f =>
funext γ a
show (f.rename Var.succ).denote (a, γ) a = f.denote γ a
rw [denote_rename f Var.succ (a, γ) γ (fun _ => rfl)]Two small consequences. A model proves consistency (interpret the base type as the empty type), and the Curry–Howard reading of a closed term computes to the expected function:
/-- **Consistency from a model.** There is no closed term of the base type: interpret the base
type as the empty type, and a closed term would denote an element of it. Through Curry–Howard:
an atomic proposition is not provable from no hypotheses. -/
theorem no_closed_term_of_base (t : Tm [] .base) : False :=
(t.denote (X := Empty) ()).elim/-- The interpretation of `curryTm` in **Set** is currying itself, `Function.curry`
(by computation: both sides reduce to `fun f a b => f (a, b)`). -/
theorem curryTm_denote (X : Type) (A B C : Ty) :
(curryTm A B C).denote (X := X) () = Function.curry := rflMathlib knows that Type is cartesian closed (as a MonoidalClosed category for the cartesian monoidal structure):
/-- Mathlib knows that the category of types is **cartesian closed**: `Type u`, with its
cartesian monoidal structure, carries a `MonoidalClosed` instance (the internal hom is the
function type and `− × B ⊣ (B → −)` is currying). This is Mathlib's instance from
`Mathlib.CategoryTheory.Monoidal.Closed.Types`. -/
theorem types_cartesianClosed : Nonempty (CategoryTheory.MonoidalClosed (Type)) :=
⟨inferInstance⟩Quantifiers as adjoints. The proofs of Theorem 3 are formalised verbatim. Mathlib states them as Galois connections, which are adjunctions between posets:
/-- **Universal quantification along `f : X → Y`**: `y` belongs to `∀_f S` when *every* `x`
over `y` lies in `S`. (Mathlib calls this `Set.kernImage f S`.) -/
def forallAlong {X Y : Type} (f : X → Y) (S : Set X) : Set Y :=
{y | ∀ x, f x = y → x ∈ S}/-- **∃ is left adjoint to substitution** (Lawvere): for predicates `S` on `X` and `T` on `Y`,
`∃_f S ⊆ T ↔ S ⊆ f*T`, where `∃_f S = f '' S` is the direct image and `f*T = f ⁻¹' T` is
pulling back (substitution). -/
theorem exists_adjoint {X Y : Type} (f : X → Y) (S : Set X) (T : Set Y) :
f '' S ⊆ T ↔ S ⊆ f ⁻¹' T := by
constructor
· intro h x hx
exact h ⟨x, hx, rfl⟩
· rintro h _ ⟨x, hx, rfl⟩
exact h hx/-- **∀ is right adjoint to substitution** (Lawvere): `f*T ⊆ S ↔ T ⊆ ∀_f S`. -/
theorem forall_adjoint {X Y : Type} (f : X → Y) (S : Set X) (T : Set Y) :
f ⁻¹' T ⊆ S ↔ T ⊆ forallAlong f S := by
constructor
· intro h y hy x hxy
apply h
show f x ∈ T
rw [hxy]
exact hy
· intro h x hx
exact h hx x rfl/-- Along the projection `π : X × Y → X`, the right adjoint is the **universal quantifier**:
`∀_π S = {x | ∀ y, (x, y) ∈ S}`. -/
theorem forall_along_fst {X Y : Type} (S : Set (X × Y)) :
forallAlong Prod.fst S = {x | ∀ y, (x, y) ∈ S} := by
ext x
constructor
· intro h y
exact h (x, y) rfl
· rintro h ⟨x', y⟩ rfl
exact h y/-- The same two adjunctions, as Mathlib states them: Galois connections
`image f ⊣ preimage f` (`Set.image_preimage`) and `preimage f ⊣ kernImage f`
(`Set.preimage_kernImage`). A Galois connection is an adjunction between posets viewed as
categories. -/
theorem quantifier_adjunctions_library {X Y : Type} (f : X → Y) :
GaloisConnection (Set.image f) (Set.preimage f) ∧
GaloisConnection (Set.preimage f) (Set.kernImage f) :=
⟨Set.image_preimage, Set.preimage_kernImage⟩/-- **Frobenius reciprocity**: `∃_f (S ∧ f*T) = ∃_f S ∧ T`. In logic: `∃x (φ(x) ∧ ψ(f x))` is
equivalent to `(∃x φ(x)) ∧ ψ` when `ψ` only depends on `y = f x`. It is one of the two
conditions (with Beck–Chevalley) that make `∃` behave well in a hyperdoctrine. -/
theorem frobenius {X Y : Type} (f : X → Y) (S : Set X) (T : Set Y) :
f '' (S ∩ f ⁻¹' T) = f '' S ∩ T := by
ext y
constructor
· rintro ⟨x, ⟨hxS, hxT⟩, rfl⟩
exact ⟨⟨x, hxS, rfl⟩, hxT⟩
· rintro ⟨⟨x, hxS, rfl⟩, hyT⟩
exact ⟨x, ⟨hxS, hyT⟩, rfl⟩Heyting algebras. The law is proved from the residuation law alone. Its counterpart in Lean's own logic is proved without excluded middle, and #print axioms confirms that it uses no axioms at all:
/-- **`¬¬(a ∨ ¬a) = ⊤` in every Heyting algebra.** Write `n = ¬(a ∨ ¬a)`. Since `a ≤ a ∨ ¬a`,
`n ∧ a ≤ ⊥`, so `n ≤ ¬a ≤ a ∨ ¬a`; hence `n ≤ n ∧ (a ∨ ¬a) ≤ ⊥`, i.e. `n = ⊥` and `¬n = ⊤`.
Only the defining law `c ≤ (a ⇨ b) ↔ c ∧ a ≤ b` is used. -/
theorem not_not_em_heyting {α : Type*} [HeytingAlgebra α] (a : α) : (a ⊔ aᶜ)ᶜᶜ = ⊤ := by
-- `x ∧ ¬x ≤ ⊥`, from the residuation law with `c = ¬x`.
have contra : ∀ x : α, xᶜ ⊓ x ≤ ⊥ := fun x => by
rw [← le_himp_iff, himp_bot]
have hn_le_compl : (a ⊔ aᶜ)ᶜ ≤ aᶜ := by
have h : (a ⊔ aᶜ)ᶜ ≤ a ⇨ ⊥ := by
rw [le_himp_iff]
exact le_trans (inf_le_inf_left _ le_sup_left) (contra (a ⊔ aᶜ))
rwa [himp_bot] at h
have hn_bot : (a ⊔ aᶜ)ᶜ ≤ ⊥ :=
calc (a ⊔ aᶜ)ᶜ ≤ (a ⊔ aᶜ)ᶜ ⊓ (a ⊔ aᶜ) := le_inf le_rfl (hn_le_compl.trans le_sup_right)
_ ≤ ⊥ := contra (a ⊔ aᶜ)
have h : ⊤ ≤ (a ⊔ aᶜ)ᶜ ⇨ ⊥ := by
rw [le_himp_iff]
exact le_trans inf_le_right hn_bot
rw [himp_bot] at h
exact top_le_iff.mp h/-- The same law in Lean's own logic: `¬¬(P ∨ ¬P)`, proved **without** the law of excluded
middle (`#print axioms` reports no axioms). Given `h : ¬(P ∨ ¬P)`, the function
`fun p => h (Or.inl p)` proves `¬P`, and then `h (Or.inr …)` is a contradiction. -/
theorem not_not_em (P : Prop) : ¬¬(P ∨ ¬P) :=
fun h => h (Or.inr fun p => h (Or.inl p))The non-Boolean Heyting algebra is handled exactly as in the second proof of Theorem 6, by connectedness:
/-- **The open sets of ℝ form a Heyting algebra that is not Boolean.** (`Opens ℝ` is a frame,
hence a Heyting algebra, in Mathlib.) For `U = (0, ∞)`, the pseudo-complement `¬U` is the
largest open set disjoint from `U`, and `U ∨ ¬U ≠ ℝ`: otherwise `U` would be open and closed,
hence `∅` or `ℝ`, because ℝ is connected (Mathlib's `isClopen_iff`). -/
theorem opens_real_not_boolean :
∃ U : TopologicalSpace.Opens ℝ, U ⊔ Uᶜ ≠ ⊤ := by
refine ⟨⟨Set.Ioi 0, isOpen_Ioi⟩, fun h => ?_⟩
set U : TopologicalSpace.Opens ℝ := ⟨Set.Ioi 0, isOpen_Ioi⟩ with hU
have hdisj : U ⊓ Uᶜ = ⊥ := inf_compl_self U
have hunion : (U : Set ℝ) ∪ (Uᶜ : TopologicalSpace.Opens ℝ) = Set.univ := by
rw [← TopologicalSpace.Opens.coe_sup, h, TopologicalSpace.Opens.coe_top]
have hinter : (U : Set ℝ) ∩ (Uᶜ : TopologicalSpace.Opens ℝ) = ∅ := by
rw [← TopologicalSpace.Opens.coe_inf, hdisj, TopologicalSpace.Opens.coe_bot]
-- So the complement of `U` (as a set) is the open set `¬U`; hence `U` is clopen.
have hcompl : (U : Set ℝ)ᶜ = (Uᶜ : TopologicalSpace.Opens ℝ) := by
ext x
constructor
· intro hx
have : x ∈ (U : Set ℝ) ∪ (Uᶜ : TopologicalSpace.Opens ℝ) := by rw [hunion]; trivial
rcases this with h1 | h2
· exact absurd h1 hx
· exact h2
· intro hx hxU
have : x ∈ (U : Set ℝ) ∩ (Uᶜ : TopologicalSpace.Opens ℝ) := ⟨hxU, hx⟩
rw [hinter] at this
exact this
have hclopen : IsClopen (U : Set ℝ) := by
refine ⟨?_, U.isOpen⟩
rw [← isOpen_compl_iff, hcompl]
exact (Uᶜ : TopologicalSpace.Opens ℝ).isOpen
rcases isClopen_iff.mp hclopen with h0 | h1
· have : (1 : ℝ) ∈ (U : Set ℝ) := by
show (1 : ℝ) ∈ Set.Ioi 0
norm_num
rw [h0] at this
exact this
· have : (-1 : ℝ) ∈ (U : Set ℝ) := by rw [h1]; trivial
have : (0 : ℝ) < -1 := this
norm_num at thisFinally, intuitionistic natural deduction, its soundness for every Heyting algebra (Theorem 4), and the two halves of Theorem 6:
/-- **Natural deduction for intuitionistic propositional logic** (IPC): `Derives Γ φ` means
`φ` is derivable from the list of hypotheses `Γ`. There is an introduction and an elimination
rule for each connective, and *no* rule for excluded middle or double-negation elimination. -/
inductive Derives : List Form → Form → Prop where
| hyp {Γ : List Form} {φ : Form} : φ ∈ Γ → Derives Γ φ
| topI {Γ : List Form} : Derives Γ .top
| botE {Γ : List Form} {φ : Form} : Derives Γ .bot → Derives Γ φ
| andI {Γ : List Form} {φ ψ : Form} : Derives Γ φ → Derives Γ ψ → Derives Γ (.and φ ψ)
| andE₁ {Γ : List Form} {φ ψ : Form} : Derives Γ (.and φ ψ) → Derives Γ φ
| andE₂ {Γ : List Form} {φ ψ : Form} : Derives Γ (.and φ ψ) → Derives Γ ψ
| orI₁ {Γ : List Form} {φ ψ : Form} : Derives Γ φ → Derives Γ (.or φ ψ)
| orI₂ {Γ : List Form} {φ ψ : Form} : Derives Γ ψ → Derives Γ (.or φ ψ)
| orE {Γ : List Form} {φ ψ χ : Form} :
Derives Γ (.or φ ψ) → Derives (φ :: Γ) χ → Derives (ψ :: Γ) χ → Derives Γ χ
| impI {Γ : List Form} {φ ψ : Form} : Derives (φ :: Γ) ψ → Derives Γ (.imp φ ψ)
| impE {Γ : List Form} {φ ψ : Form} : Derives Γ (.imp φ ψ) → Derives Γ φ → Derives Γ ψ/-- **Soundness of intuitionistic logic for Heyting algebras**: if `φ` is derivable from `Γ`,
then in *every* Heyting algebra and for *every* valuation, `⋀Γ ≤ ⟦φ⟧`. Each rule is one law of
Heyting algebras: `→I` and `→E` are the two directions of `c ≤ (a ⇨ b) ↔ c ∧ a ≤ b`, and
`∨E` uses distributivity `c ∧ (a ∨ b) = (c ∧ a) ∨ (c ∧ b)`. -/
theorem derives_sound {α : Type*} [HeytingAlgebra α] (v : ℕ → α) {Γ : List Form} {φ : Form}
(h : Derives Γ φ) : ctxEval v Γ ≤ φ.eval v := by
induction h with
| hyp hm => exact ctxEval_le_of_mem v hm
| topI => exact le_top
| botE _ ih => exact ih.trans bot_le
| andI _ _ ih₁ ih₂ => exact le_inf ih₁ ih₂
| andE₁ _ ih => exact ih.trans inf_le_left
| andE₂ _ ih => exact ih.trans inf_le_right
| orI₁ _ ih => exact ih.trans le_sup_left
| orI₂ _ ih => exact ih.trans le_sup_right
| @orE Γ φ ψ χ _ _ _ ih ih₁ ih₂ =>
-- `c ≤ a ∨ b`, `a ∧ c ≤ x` and `b ∧ c ≤ x` give `c = c ∧ (a ∨ b) = (c ∧ a) ∨ (c ∧ b) ≤ x`.
calc ctxEval v Γ ≤ ctxEval v Γ ⊓ (φ.eval v ⊔ ψ.eval v) := le_inf le_rfl ih
_ = (ctxEval v Γ ⊓ φ.eval v) ⊔ (ctxEval v Γ ⊓ ψ.eval v) := inf_sup_left _ _ _
_ ≤ χ.eval v := by
apply sup_le
· rw [inf_comm]; exact ih₁
· rw [inf_comm]; exact ih₂
| @impI Γ φ ψ _ ih =>
show ctxEval v Γ ≤ φ.eval v ⇨ ψ.eval v
rw [le_himp_iff, inf_comm]
exact ih
| impE _ _ ih₁ ih₂ =>
exact (le_inf ih₁ ih₂).trans himp_inf_le/-- `¬¬(p ∨ ¬p)` **is** derivable intuitionistically. The derivation: assume
`h : ¬(p ∨ ¬p)`; to refute it, prove `p ∨ ¬p` by proving `¬p` (assume `p`, then `h (inl p)` is
absurd) and applying `inr`. -/
theorem derives_not_not_em (n : ℕ) :
Derives [] (Form.neg (Form.neg (.or (.atom n) (Form.neg (.atom n))))) := by
apply Derives.impI
apply Derives.impE (Derives.hyp (List.mem_singleton_self _))
apply Derives.orI₂
apply Derives.impI
apply Derives.impE (Derives.hyp (List.mem_cons_of_mem _ (List.mem_singleton_self _)))
exact Derives.orI₁ (Derives.hyp (List.mem_cons_self))/-- **Excluded middle is not derivable** in intuitionistic propositional logic. If it were,
soundness would force `U ∨ ¬U = ⊤` for every open set `U ⊆ ℝ`, contradicting
`opens_real_not_boolean`. (The semantics does the work: no search through derivations.) -/
theorem not_derives_em (n : ℕ) : ¬ Derives [] (.or (.atom n) (Form.neg (.atom n))) := by
intro h
obtain ⟨U, hU⟩ := opens_real_not_boolean
have hs := derives_sound (fun _ => U) h
apply hU
apply top_le_iff.mp
simpa [ctxEval, Form.eval, Form.neg, himp_bot] using hsWhat is not formalised. The interpretation in an arbitrary cartesian closed category (Lean has one model, Type; Mathlib's MonoidalClosed API would be the place to generalise), the freeness of the syntactic category, Friedman's theorem, and the completeness theorem (Theorem 5), whose Lindenbaum–Tarski construction needs a quotient of formulas by interderivability. Note also that Lean's ambient logic is classical (Classical.choice is available). The proofs above that report no axioms are constructive, but the formal system as a whole is not intuitionistic. That is why we formalised intuitionistic logic as an object language (Derives) instead of relying on Lean's own.
Countermodels and coarse models
A Heyting algebra in which a formula is not is a proof that the formula is not intuitionistically derivable (by Theorem 4). Such countermodels can be found by search. The first experiment enumerates every topology on at most three points and evaluates eight classical tautologies in each.
"""Heyting algebras of open sets: where excluded middle fails, and where it cannot.
Every topology is a Heyting algebra: meet is intersection, join is union, and
U => V is the interior of (X \\ U) | V, the largest open W with W & U <= V.
We enumerate all 29 topologies on a three-point set, check the Heyting law
W <= (U => V) iff W & U <= V exhaustively, find which topologies are
Boolean, and evaluate classical tautologies under every valuation.
A failure is a genuine countermodel: by the soundness theorem proved in the
lesson (and in Lean), a formula that is not top in some Heyting algebra is not
derivable in intuitionistic propositional logic. Success on these small spaces
is only finite evidence of derivability.
"""
import itertools
def subsets(points):
"""All subsets of ``points`` as frozensets, smallest first."""
pts = sorted(points)
return [frozenset(c) for r in range(len(pts) + 1)
for c in itertools.combinations(pts, r)]
def is_topology(opens, space):
"""Contains the empty set and the space, closed under union and meet."""
if frozenset() not in opens or space not in opens:
return False
return all(a | b in opens and a & b in opens for a in opens for b in opens)
def all_topologies(n):
"""All topologies on {0, ..., n-1}, as a list of frozensets of opens."""
space = frozenset(range(n))
middle = [s for s in subsets(space) if s and s != space]
found = []
for k in range(len(middle) + 1):
for family in itertools.combinations(middle, k):
opens = frozenset(family) | {frozenset(), space}
if is_topology(opens, space):
found.append(opens)
return found
def implies(opens, u, v):
"""Heyting implication: the union of all opens W with W & u <= v."""
return frozenset().union(*[w for w in opens if w & u <= v])
def neg(opens, u):
"""Pseudo-complement: the largest open set disjoint from u."""
return implies(opens, u, frozenset())
def residuation_holds(opens):
"""Check W <= (U => V) iff W & U <= V for all opens W, U, V."""
return all((w <= implies(opens, u, v)) == (w & u <= v)
for w in opens for u in opens for v in opens)
def is_boolean(opens, space):
"""Boolean iff U | not U is the whole space for every open U."""
return all(u | neg(opens, u) == space for u in opens)
def evaluate(formula, opens, valuation):
"""Value of a formula: an atom name or (op, args...), op in and/or/imp/not."""
if isinstance(formula, str):
return valuation[formula]
op, *args = formula
vals = [evaluate(a, opens, valuation) for a in args]
if op == "and":
return vals[0] & vals[1]
if op == "or":
return vals[0] | vals[1]
if op == "imp":
return implies(opens, vals[0], vals[1])
return neg(opens, vals[0])
def atoms(formula):
"""The set of atom names in a formula."""
if isinstance(formula, str):
return {formula}
return set().union(*[atoms(a) for a in formula[1:]])
def countermodel(formula, max_points=3):
"""First (space, opens, valuation) where the formula is not top, or None."""
names = sorted(atoms(formula))
for n in range(1, max_points + 1):
space = frozenset(range(n))
for opens in all_topologies(n):
ordered = sorted(opens, key=lambda s: (len(s), sorted(s)))
for values in itertools.product(ordered, repeat=len(names)):
valuation = dict(zip(names, values))
if evaluate(formula, opens, valuation) != space:
return space, opens, valuation
return None
FORMULAS = [
("p or not p", ("or", "p", ("not", "p"))),
("not not (p or not p)", ("not", ("not", ("or", "p", ("not", "p"))))),
("not not p -> p", ("imp", ("not", ("not", "p")), "p")),
("p -> not not p", ("imp", "p", ("not", ("not", "p")))),
("((p -> q) -> p) -> p", ("imp", ("imp", ("imp", "p", "q"), "p"), "p")),
("not p or not not p", ("or", ("not", "p"), ("not", ("not", "p")))),
("(p -> q) or (q -> p)", ("or", ("imp", "p", "q"), ("imp", "q", "p"))),
("not (p and q) -> not p or not q",
("imp", ("not", ("and", "p", "q")), ("or", ("not", "p"), ("not", "q")))),
]
def show(s):
"""Print a set of points compactly, e.g. {0,1}."""
return "{" + ",".join(str(x) for x in sorted(s)) + "}"
def main():
print("Topologies on n points; residuation law; how many are Boolean:")
for n in range(1, 4):
space = frozenset(range(n))
tops = all_topologies(n)
ok = all(residuation_holds(t) for t in tops)
boolean = sum(is_boolean(t, space) for t in tops)
print(f" n = {n}: {len(tops):2d} topologies, Heyting law holds in all:"
f" {ok}, Boolean: {boolean}")
sierp = frozenset([frozenset(), frozenset([1]), frozenset([0, 1])])
u = frozenset([1])
print("Sierpinski space, opens {}, {1}, {0,1}; U = {1}:")
print(f" not U = {show(neg(sierp, u))}, U or not U = "
f"{show(u | neg(sierp, u))}, not not U = {show(neg(sierp, neg(sierp, u)))}")
print()
print("Classical tautologies on all spaces with at most 3 points:")
for name, formula in FORMULAS:
found = countermodel(formula)
if found is None:
print(f" {name:<34} top in every case checked")
else:
space, opens, val = found
where = ", ".join(f"{k}={show(v)}" for k, v in sorted(val.items()))
print(f" {name:<34} FAILS: {len(space)} points, "
f"{len(opens)} opens, {where}")
print()
print("Epistemic status: exhaustive over all topologies on at most three")
print("points. Each FAILS line is a genuine countermodel, so by soundness that")
print("formula is not derivable intuitionistically. A formula that is top in")
print("every case checked is only supported by finite evidence here; the")
print("derivations (e.g. of not not (p or not p)) are what prove it.")
if __name__ == "__main__":
main()Two points already refute excluded middle, double-negation elimination and Peirce's law. That is the Sierpiński space: two possible worlds, one of which "knows more". Weak excluded middle , the De Morgan law and Dummett's law need three points, arranged in a "V" in which two incomparable opens meet only in . These laws axiomatise intermediate logics between intuitionistic and classical logic. The first two are equivalent over intuitionistic logic and give the logic usually called KC. Dummett's law gives the strictly stronger Gödel–Dummett logic LC. The search counts Boolean topologies too: they are exactly the partition topologies, 1, 2 and 5 of them (the Bell numbers).
The second experiment looks at the λ-calculus side. Church numerals are pairwise distinct normal forms. In a finite model, however, must eventually repeat.
"""Interpreting λ-terms in finite sets: sound, but too coarse to be complete.
The interpretation of the simply typed λ-calculus in Set sends the base type
to a set X. Two experiments with exact, exhaustive computation:
1. Church numerals n = λf.λx. f(f(...f(x))) are distinct normal forms, so no
two are βη-equal. Over a finite X of size m their meanings f -> f^n must
eventually repeat; we find the first coincidence for m = 1, 2, 3, 4.
2. The closed terms of type A×A -> A×A have four normal forms. Over X = {0, 1}
there are 256 functions X×X -> X×X, and exactly the four definable ones are
natural (commute with every map X -> X), as Yoneda predicts.
Friedman's theorem (1975) says that with an infinite base set, equality of
meanings is exactly βη-equality; part 1 shows why finiteness breaks this.
"""
import itertools
import math
def all_maps(m):
"""All functions {0..m-1} -> {0..m-1}, as tuples of images."""
return list(itertools.product(range(m), repeat=m))
def compose_power(f, n):
"""The n-th iterate f^n of a map given as a tuple."""
result = tuple(range(len(f)))
for _ in range(n):
result = tuple(f[x] for x in result)
return result
def numeral_meaning(n, m):
"""Meaning of the Church numeral n over an m-element set: f -> f^n."""
return tuple(compose_power(f, n) for f in all_maps(m))
def first_coincidence(m, limit=40):
"""Smallest (a, b), a < b <= limit, with numerals a, b equal over m points."""
seen = {}
for n in range(limit + 1):
meaning = numeral_meaning(n, m)
if meaning in seen:
return seen[meaning], n
seen[meaning] = n
return None
def definable_pair_maps():
"""Meanings of the 4 closed normal terms λp.(πᵢ p, πⱼ p) of type A×A->A×A."""
def term(i, j):
return lambda a, b: ((a, b)[i], (a, b)[j])
return {f"(p{i + 1}, p{j + 1})": term(i, j) for i in (0, 1) for j in (0, 1)}
def natural_pair_maps(m):
"""All g : X×X -> X×X, X of size m, with g(h a, h b) = (h×h)(g(a, b))."""
pts = [(a, b) for a in range(m) for b in range(m)]
maps = all_maps(m)
found = []
for images in itertools.product(pts, repeat=len(pts)):
g = dict(zip(pts, images))
if all(g[(h[a], h[b])] == (h[g[(a, b)][0]], h[g[(a, b)][1]])
for h in maps for (a, b) in pts):
found.append(g)
return found
def main():
print("1. Church numerals over an m-element base set X")
print(" (numeral n means f -> f^n; gap = difference of the two numerals)")
for m in range(1, 5):
a, b = first_coincidence(m)
lcm = math.lcm(*range(1, m + 1))
print(f" m = {m}: {len(all_maps(m)):3d} maps; numerals {a:2d} and"
f" {b:2d} first agree; gap {b - a:2d}; lcm(1..{m}) = {lcm:2d}")
print(" Distinct normal forms, same meaning: finite models are not complete.")
print()
print("2. Closed terms of type A*A -> A*A, interpreted over X = {0, 1}")
natural = natural_pair_maps(2)
pts = [(a, b) for a in range(2) for b in range(2)]
definable = definable_pair_maps()
print(f" functions X*X -> X*X: {4 ** 4}; natural ones: {len(natural)}")
tables = [tuple(g[p] for p in pts) for g in natural]
for name, t in definable.items():
table = tuple(t(*p) for p in pts)
print(f" term {name}: natural = {table in tables}")
print()
print("Epistemic status: exact and exhaustive for the sets checked. Part 1")
print("exhibits genuine pairs of non-convertible terms that a finite model")
print("cannot tell apart; it does not test Friedman's theorem, which needs an")
print("infinite base set. Part 2 checks naturality only for endomaps of a")
print("two-element set; the general statement is the Yoneda lemma.")
if __name__ == "__main__":
main()On an -element set the first coincidence is . The output shows this for , and it follows in general from the structure of the full transformation monoid. Finite models are therefore sound but not complete for βη-equality, which is why Friedman's theorem needs an infinite base set. The second part shows the other side of the coin. Of the functions on a two-element set , exactly four commute with every map , and they are precisely the four that are definable by closed λ-terms. By the Yoneda lemma, has four elements. This is the first glimpse of parametricity: definable terms are uniform in the interpretation of the base type.
Explore: what truth tables cannot see
A classical truth table is evaluation in the two-element Boolean algebra . Compare with below. Both are tautologies, so the truth table declares them equivalent.
Two classical tautologies
Equivalent in the two-element Boolean algebra, but not intuitionistically
Read as: ¬¬(p ∨ ¬p)
Read as: p ∨ ¬p
Use the symbols ¬ ∧ ∨ → ↔, the words not, and, or, implies, iff, or ASCII ~ & | -> <->. Variables are single lowercase letters. ¬ binds tightest, then ∧, ∨, →, ↔; p → q → r means p → (q → r).
Tautology — true in all 2 rows.
Equivalent — the two formulas agree in all 2 rows.
| p | ¬p | p ∨ ¬p | ¬(p ∨ ¬p) | ¬¬(p ∨ ¬p) | p ∨ ¬p | Rows where they differ |
|---|---|---|---|---|---|---|
| T | F | T | F | T | T | |
| F | T | T | F | T | T |
2 rows: one for every way of making the 1 variables true or false.
Things to try:
- Replace the comparison by
¬¬p → p, then by((p → q) → p) → p(Peirce's law). Every one is a classical tautology, and the computation section exhibits a two-point topological space in which each fails. - Try
(p → q) ∨ (q → p). It is a tautology too, but it is not intuitionistically derivable. Its smallest topological countermodel has three points. - Explain why no truth table can ever separate from . (Hint: in a Boolean algebra .) This is why Heyting algebras, Kripke models or topological spaces are needed to study intuitionistic logic.
Exercises
1. Categorical logic
Warm-upHumanIn the Heyting algebra of open subsets of , let . What are and ?
2. Categorical logic
Warm-upHumanWhich of these categories are cartesian closed? (Choose all that apply.)
3. Categorical logic
CoreHumanIn the three-element Heyting algebra , for how many elements does hold?
4. Categorical logic
CoreHumanSince , the universal quantifier is a right adjoint, and right adjoints preserve limits (in a poset: meets). Which logical law is an instance of exactly this fact?
5. Categorical logic
CoreHumanIn the proof that intuitionistic logic is sound for Heyting algebras, one rule needs the distributive law . Which rule, and why does the distributive law hold in every Heyting algebra?
6. Categorical logic
CoreFormalWith forallAlong f S = {y | ∀ x, f x = y → x ∈ S}, which Lean statement says that ∀ is right adjoint to pulling back along f : X → Y (for S : Set X, T : Set Y)?
7. Categorical logic
CoreHumanHow many closed βη-normal terms of type are there, for a base type ?
8. Categorical logic
StretchHumanA student claims: "Intuitionistic logic proves ; that is what rejecting excluded middle means." Which response is correct?
9. Categorical logic
StretchComputationalA finite topology is given as a set opens of frozensets. Write neg(opens, u), returning the pseudo-complement of the open set u (the union of all open sets disjoint from u), and is_boolean(opens, space), returning True exactly when u | neg(opens, u) == space for every open u.
Common misconceptions
Misconception
"Categorical semantics replaces set-theoretic semantics." It contains it. is one cartesian closed category (and one Boolean topos) among many: Heyting algebras, presheaf and sheaf categories, realizability toposes, categories of domains. Each is useful for a different purpose. Ordinary mathematics is still written in, and about, the model . The categorical view tells you which theorems remain true when you change the model.
Misconception
"Intuitionistic logic asserts that excluded middle is false." It does not assume excluded middle, and it proves , so excluded middle can never be refuted. is not derivable: it evaluates to in the two-element Boolean algebra. Every intuitionistic theorem is also a classical theorem.
Misconception
"Since is complete for βη-equality (Friedman), it is also complete for provability." No. Friedman's theorem is about equations between terms. For inhabitation (Curry–Howard provability), is classical. Interpret the base types as any sets: the type of Peirce's law always gets a non-empty interpretation (check the cases and ), yet no closed λ-term has this type. Detecting intuitionistic unprovability needs non-Boolean models.
Misconception
"Cartesian closed means having all limits." A CCC needs only finite products and exponentials. is cartesian closed but has no infinite products, and a finite chain is a Heyting algebra regardless of completeness. Conversely, has all limits but is not cartesian closed.
Many ways of seeing
Topology— Truth values are open sets
The open sets of a space form a Heyting algebra. A proposition interpreted as an open set is "true at the points of ". Openness is the mathematical shape of observability: if a property holds at a point, it holds nearby. Excluded middle fails because a property and its pseudo-complement can both fail at a boundary point. This is more than an example. Tarski (1938) proved that intuitionistic propositional logic is complete for the topological semantics on , so a formula is derivable if and only if it evaluates to under every assignment of open subsets of . Stone (1937) represented Heyting algebras, then called "Brouwerian logics", by open sets. In modern form, every Heyting algebra embeds in the Heyting algebra of up-sets of its prime filters, and these up-sets are the open sets of a topology. Finite Kripke models are the special case of finite spaces, whose open sets are the up-sets of a preorder. In the other direction, frames (complete lattices in which finite meets distribute over arbitrary joins; equivalently, complete Heyting algebras) are the "spaces without points" of locale theory, and sheaves on a space form a topos whose internal logic is this topological logic, extended to quantifiers.
Geometry— ∃ is a projection
Theorem 3 says that existential quantification is the direct image under a projection, the shadow of a set. Eliminating a quantifier is therefore a theorem in geometry. The Tarski–Seidenberg theorem, that the projection of a semialgebraic set is semialgebraic, is equivalent to quantifier elimination for the real field. Chevalley's theorem, that the image of a constructible set under a morphism of varieties over an algebraically closed field is constructible, is the corresponding statement for algebraically closed fields (see model theory and algebraic geometry). is the dual "everything over this point" operation. Beck–Chevalley says that taking shadows commutes with base change. For instance, for a subset of the base, the shadow of the part of lying over is the shadow of intersected with .
Algebra— Free algebras measure a logic
The Lindenbaum–Tarski algebra on propositional variables is the free Heyting algebra on generators. Free algebras show how much a logic can distinguish. The free Boolean algebra on one generator has four elements, . The free Heyting algebra on one generator is infinite: the Rieger–Nishimura lattice (Rieger 1949, Nishimura 1960) contains as pairwise inequivalent formulas. Algebraically, soundness and completeness (Theorems 4 and 5) say that intuitionistic propositional logic is the equational theory of Heyting algebras, a variety in the sense of universal algebra. Intermediate logics such as Dummett's correspond to subvarieties: Dummett's law axiomatises the subvariety generated by the linearly ordered Heyting algebras.
Computation— Compiling through a cartesian closed category
The interpretation of Theorem 2 is a compiler. It translates λ-terms, with their named variables, into variable-free combinators: projections, pairing, and . The Categorical Abstract Machine of Cousineau, Curien and Mauny (1985, journal version 1987) executes exactly these CCC combinators, and it gave the original Caml implementation its name. In the other direction, Curry–Howard makes proof assistants possible. Lean checks a proof by type-checking a term, and normalising a proof is running a program. #print axioms exposes the constructive/classical boundary: the proof of ¬¬(P ∨ ¬P) in this lesson uses no axioms, whereas proofs that use excluded middle depend on Classical.choice.
Logic— Hyperdoctrines: logic over a category of contexts
Lawvere's hyperdoctrines organise first-order logic categorically. There is a base category of contexts (objects are lists of variables, morphisms are tuples of terms), a poset or Heyting algebra of formulas in each context, substitution functors , and quantifiers as their adjoints, subject to Beck–Chevalley and Frobenius. Equality is along a diagonal. This is the logic of a first-order theory with every structural rule made explicit, and the same pattern governs dependent type theory. There, Seely (1984) matched - and -types with the left and right adjoints to pullback in a locally cartesian closed category. The precise correspondence needs care with substitution, which holds only up to isomorphism (Hofmann 1994).
Physics— A logic that is not Heyting
Birkhoff and von Neumann (1936) proposed that the propositions about a quantum system are the closed subspaces of a Hilbert space, ordered by inclusion. Meet is intersection and join is closed span. This lattice is not distributive. In , take three distinct lines : then , but . A Heyting algebra is always distributive, because is a left adjoint, so in quantum logic conjunction with has no right adjoint. There is no implication obeying the deduction theorem. This contrast clarifies what Heyting algebras capture. It also motivates the topos-theoretic approaches to quantum theory of Isham, Butterfield and Döring, which replace the non-distributive lattice by a Heyting algebra of subobjects in a presheaf topos. These remain a research programme, not settled physics.
The landscape and where to go next
- Dependent types and locally cartesian closed categories. Replacing and by and moves the correspondence from CCCs to locally cartesian closed categories, where every slice is cartesian closed. Lean's own type theory is a dependent type theory of this kind, with inductive types and universes added.
- Toposes. A topos is a category in which the subobjects of each object form a Heyting algebra, functorially, with quantifiers as adjoints. In other words, it is a hyperdoctrine built from the category itself. Its internal logic is higher-order intuitionistic logic (Lambek and Scott, Part II).
- Homotopy type theory. Identity types in dependent type theory have models in which equalities are paths. This leads to homotopy type theory and its semantics in higher categories.
- Proof theory. Normalisation of proofs (Gentzen, Prawitz) is β-reduction under Curry–Howard. Categorical coherence theorems are often normalisation theorems in disguise (see proof theory).
- Linear logic and monoidal closed categories. Dropping the diagonal (duplication of hypotheses) replaces cartesian closed categories by symmetric monoidal closed ones; see monoidal categories.
History and global context
- Intuitionism. L. E. J. Brouwer (Netherlands) criticised the unrestricted use of excluded middle from 1907 onwards. Valery Glivenko (Moscow) proved his double-negation theorem in 1929. Arend Heyting (Netherlands) formalised intuitionistic logic in 1930, and Andrey Kolmogorov (Moscow) gave its "problem" interpretation in 1932. Together with Brouwer and Heyting this became the Brouwer–Heyting–Kolmogorov interpretation.
- Algebraic and topological semantics. Marshall Stone (1937) and Alfred Tarski (1938) connected intuitionistic logic with lattices of open sets. McKinsey and Tarski developed the algebra of topology in the 1940s. Ladislav Rieger (Prague, 1949) and Iwao Nishimura (Japan, 1960) described the free Heyting algebra on one generator, and Saul Kripke (1965) introduced his possible-worlds semantics.
- Propositions as types. Haskell Curry noticed the match between combinators and axioms of implicational logic (1934, and with Robert Feys in 1958). William Howard's notes on "formulae-as-types" circulated in 1969 and were published in 1980.
- Categories. Samuel Eilenberg and Saunders Mac Lane introduced categories in 1945, and Daniel Kan introduced adjoint functors in 1958. F. William Lawvere's thesis (1963) and papers "Adjointness in foundations" (1969) and on equality in hyperdoctrines (1970) made adjoints the organising principle of logic. Joachim Lambek's "Deductive systems and categories" (1968–1972) and "From λ-calculus to cartesian closed categories" (1980) completed the third side of the correspondence, and Lambek and Philip Scott's book (1986) became its standard reference. Harvey Friedman's completeness theorem for set-theoretic models appeared in 1975. Robert Seely's work on locally cartesian closed categories appeared in 1984.
Further reading
- J. Lambek and P. J. Scott, Introduction to Higher Order Categorical Logic (1986). Part I covers cartesian closed categories and the λ-calculus, Part II toposes and higher-order logic.
- Steve Awodey, Category Theory (2nd edition, 2010). Chapters 6–10 cover exponentials, Heyting algebras, the λ-calculus and adjoints, with quantifiers as adjoints.
- Bart Jacobs, Categorical Logic and Type Theory (1999). Fibrations, hyperdoctrines and dependent types.
- Andrew M. Pitts, "Categorical logic", in Handbook of Logic in Computer Science, vol. 5 (2000). A concise survey.
- Morten Heine Sørensen and Paweł Urzyczyn, Lectures on the Curry–Howard Isomorphism (2006).
- A. S. Troelstra and D. van Dalen, Constructivism in Mathematics (2 vols., 1988). Intuitionistic logic and its semantics.
- Saunders Mac Lane and Ieke Moerdijk, Sheaves in Geometry and Logic (1992). The next step: the internal logic of toposes.