Canonical, or just convenient?
Every finite-dimensional vector space over a field is isomorphic to its dual : both have dimension . It is also isomorphic to its double dual . Yet working mathematicians treat these two isomorphisms completely differently. Nobody hesitates to identify with ; identifying with is regarded as a choice, made only when extra structure (an inner product, a basis) is around.
What is the difference? To write down you must choose something — a basis , giving — and a different basis gives a different isomorphism. The map needs no choice at all:
It is defined by the same recipe for every vector space at once, and it is compatible with every linear map between them. In 1945 Samuel Eilenberg and Saunders Mac Lane turned this feeling into a definition, and the definition needed a whole new language: to say what "the same recipe for every space, compatible with all maps" means, they had to define categories and functors first. This lesson is about the notion they were really after — the natural transformation — and about the notion of "sameness" of categories it makes possible: equivalence.
Morphisms between functors
A functor draws a picture of inside : each object becomes , each arrow becomes . Given two such pictures and of the same category, a natural transformation is a way of sliding the first picture onto the second: an arrow for each object , chosen so that sliding is compatible with every arrow of the picture. Compatibility is a single equation, drawn as a square:
Two slogans help, as long as you remember that they are slogans and the square is the definition.
- Natural means uniform. A natural family cannot treat different objects by different ad hoc rules, because the arrows between objects force the components to agree. We will see that the only natural ways of turning a pair of elements of an arbitrary set into one element of are "take " and "take ": every other rule, such as "take the smaller one", needs extra structure on .
- Natural means basis-free. In linear algebra, the arrows include all changes of basis. A natural construction cannot depend on a basis, because it must commute with every change of basis.
There is also a geometric picture, made precise in the topology viewpoint below: a natural transformation is to functors what a homotopy is to continuous maps — a continuous deformation of one into the other, through a "cylinder" .
Definitions
Throughout, , , are categories and composition is written (" after ").
Definition— natural transformation
Let be functors. A natural transformation is a family of morphisms of , the components
such that for every morphism of the naturality square commutes:
Definition— natural isomorphism
A natural transformation is a natural isomorphism if every component is an isomorphism in . We then write and say and are naturally isomorphic. A family of isomorphisms that is not natural is sometimes called "unnatural", and the phrase "naturally isomorphic" always refers to some pair of functors.
Definition— vertical composition and the functor category
If and , their vertical composite has components . The identity has components . When is small, the functor category (also written ) has the functors as objects and the natural transformations between them as morphisms.
Definition— whiskering
For with , and functors , , the whiskered transformations and have components and . Both are natural (apply to the arrow, or to the square).
Definition— full, faithful, essentially surjective
A functor is faithful if each map , , is injective; full if each is surjective; fully faithful if each is bijective. It is essentially surjective if every object of is isomorphic to for some object of .
Definition— equivalence of categories
An equivalence of categories is a functor together with a functor (a quasi-inverse) and natural isomorphisms
and are equivalent, , if there is an equivalence between them. An isomorphism of categories is the stricter notion and on the nose.
Note
Equivalence is the right notion of sameness for categories precisely because it is phrased with isomorphisms instead of equalities of objects. Asking two objects of a category to be equal is almost never meaningful; asking them to be isomorphic is. Equivalence applies the same principle one level up.
Examples and non-examples
Example— The double dual
Let be the category of vector spaces over and linear maps. The double dual is a covariant functor : a linear map gives , , and then , . The maps form a natural transformation : for and ,
On the full subcategory of finite-dimensional spaces every is an isomorphism, so is a natural isomorphism there.
Example— The determinant, natural in the ring
Fix . For a commutative ring , let be the group of invertible matrices over and the group of units. Both are functors : a ring homomorphism acts on matrices entrywise and on units by restriction. The determinant is a group homomorphism, and the naturality square says
This holds because is a polynomial with integer coefficients in the entries, and preserves sums, products and integers. So is natural. By contrast, "the trace of , as an element of " is not even a family of maps (the trace of an invertible matrix need not be a unit), and the trace is not a group homomorphism: naturality is a condition on families of morphisms in the target category.
Example— Equivariant maps are natural transformations
A group is a category with one object and one invertible arrow for each element of . A functor is a set with an action of , i.e. a -set. A natural transformation has one component , and naturality at the arrow says : natural transformations between -sets are exactly the -equivariant maps. So the functor category is the category of -sets, and is the category of linear representations of .
Example— Commutative squares are natural transformations
Let be the category with one non-identity arrow. A functor is an arrow of , and a natural transformation from to is a pair with — a commutative square. The functor category is the arrow category of .
Example— Polymorphic functions
On , let be the set of finite lists of elements of , with applying to every entry. Reversal is natural: relabelling the entries and then reversing gives the same list as reversing and then relabelling. So is , , and , "drop the first entry". "Sort the list in increasing order" is not a natural transformation of : it is not even defined for an arbitrary set , since it needs an order on , and on it fails to commute with .
Example— Abelianisation is natural; the centre is not even a functor
For a group let . A homomorphism maps commutators to commutators, so it induces , and the quotient maps satisfy : is natural. The centre looks just as canonical, but cannot be made into a functor at all, whatever we try to do on morphisms: the composite (a transposition generates the first copy; the sign map is the second) is the identity, while and , so a functor would have to factor through the trivial group . (On the groupoid of groups and isomorphisms the centre is a functor, and the inclusions are natural there: which arrows are allowed matters.)
Example— Non-example: a basis is not natural
Given a basis of , the dual basis gives an isomorphism , . Already the shape of a naturality square is wrong: a linear map gives , pointing the other way, so there is no square to check. The best we can ask is , i.e. that preserves the bilinear form . For the dot product on this holds only for orthogonal — 8 of the 48 invertible maps of , as the computation below shows.
Example— Equivalent but not isomorphic
Let be the category whose objects are the natural numbers, with the set of matrices over and composition matrix multiplication. The functor , , , is an equivalence (proved below). The two categories are not isomorphic: has one object of each dimension, has a proper class of them. In the same way, is equivalent to its full subcategory on the sets , and a nonempty category in which all objects are isomorphic and every object has only the identity as endomorphism is equivalent to the category with one object and one arrow.
Theorems and proofs
Theorem— Theorem 1 (the functor category)
For categories and , vertical composition of natural transformations is well defined, associative and unital, so functors and natural transformations form a category . If is small and locally small, its hom-classes are sets.
Proof
Let and , and . Using naturality of and then of ,
so is natural. The identity components are natural because . Associativity and the unit laws hold componentwise, because they hold in . If is small and locally small, the natural transformations are elements of the set , so they form a set.
∎
Theorem— Theorem 2 (natural isomorphisms are the isomorphisms of the functor category)
A natural transformation is an isomorphism in if and only if every component is an isomorphism in .
Proof
If is inverse to in the functor category, then componentwise and . Conversely, suppose each is invertible and put . We must show that is natural: for . Start from the naturality of , , compose with on the left and with on the right:
The point is that inverses of components are automatically natural; nothing new must be checked.
∎
Theorem— Theorem 3 (naturality forces uniformity)
(a) Let be the functor , . Every natural transformation is one of the two projections: either for all , or for all .
(b) The only natural transformation is the identity.
Proof
(a) Let and let . Given any set and , let be the function , . Then , and naturality at gives
If this is for every ; if it is . Both projections are indeed natural, since followed by a projection is the projection followed by .
(b) If is natural, take and with . Naturality gives .
∎
The proof used a single test object: a two-element set and one well-chosen element of . This is the first appearance of the Yoneda lemma: naturally in , and natural transformations out of correspond to elements of the target at .
Example— Natural endomorphisms of the identity on abelian groups
The same test-object argument computes the natural transformations . Let . For an abelian group and , the homomorphism , , gives . Conversely, multiplication by any is natural. So these natural transformations are exactly "multiplication by ", , and composition corresponds to multiplication of integers. On the same argument shows ; but is a homomorphism for every group only when or (look at the free group on two letters), so the identity functor of has just two natural endomorphisms.
Theorem— Theorem 4 (the double dual)
is a natural transformation on , and a natural isomorphism on .
Proof
Naturality is the calculation in the first example. For : if , extend to a basis and let be the coordinate functional of ; then , so is injective. Since , an injective linear map is bijective.
∎
For infinite-dimensional , is still injective (the same argument, extending to a basis using Zorn's lemma) but never surjective: by the Erdős–Kaplansky theorem, when is infinite. So naturality and invertibility are different questions — is natural everywhere and invertible only in finite dimension.
Theorem— Theorem 5 (V is not naturally isomorphic to V*)
(a) The dual is a functor , while the identity is a functor . A natural transformation requires two functors with the same domain and codomain, so "" is not a meaningful statement.
(b) Restrict to the groupoid of finite-dimensional spaces and linear isomorphisms, where , is a covariant functor. If has more than three elements, there is no natural isomorphism on — not even on its full subcategory of one-dimensional spaces.
Proof
(a) is a matter of types: reverses the direction of arrows, does not.
(b) A natural consists of linear maps , i.e. bilinear forms , with for every isomorphism . Evaluating at and then at gives
Take and for . Every bilinear form on is with , and invariance gives . A field with more than three elements has some with , because has at most two roots . Then , so is not an isomorphism.
∎
Over and every unit satisfies , and small exceptions really occur: on the pairing is invariant under all of , because every invertible matrix over has determinant . The second computation below finds all such exceptions for small and . This is why careful statements of " naturally" specify both the morphisms and the field.
Theorem— Theorem 6 (characterisation of equivalences)
A functor is part of an equivalence of categories if and only if it is full, faithful and essentially surjective. The "if" direction uses the axiom of choice (for a proper class of objects, a global form of it).
Proof
() Let , and be as in the definition.
Faithful. For , naturality of says , so . Thus is determined by : if then .
Essentially surjective. Every object of satisfies , via .
Full. By symmetry ( is a quasi-inverse of , with ), is faithful too. Let and put . By naturality of ,
and since is faithful, .
() For each object of choose an object of and an isomorphism (possible by essential surjectivity and choice). For , the arrow is of a unique arrow , because is full and faithful; call it . Uniqueness makes a functor: , so , and similarly for identities. By construction , so is a natural isomorphism.
For an object of , let be the unique arrow with . It is an isomorphism: if is the unique arrow with , then , so by faithfulness, and likewise in the other order. Naturality of can be checked after applying the faithful functor : for ,
where the middle step is naturality of at . Hence , and is an equivalence.
∎
Theorem— Corollary (linear algebra is matrix algebra)
For every field the functor , , is an equivalence of categories.
Proof
It is fully faithful because linear maps correspond bijectively to matrices, compatibly with composition. It is essentially surjective because a space of dimension has a basis, i.e. an isomorphism . Theorem 6 gives a quasi-inverse — which chooses a basis of every finite-dimensional space. That choice is exactly what a quasi-inverse costs, and exactly why basis-free linear algebra and matrix algebra are "the same subject" without being "the same thing".
∎
Natural transformations in Lean and Mathlib
Mathlib writes a natural transformation as α : F ⟶ G — a morphism in the functor category C ⥤ D — with components α.app X and the field α.naturality. Composition is written in diagrammatic order: f ≫ g means "first f, then g", that is . So the naturality square appears as F.map f ≫ α.app B = α.app A ≫ G.map f.
Uniformity. First the functor and Theorem 3, stated twice: once with plain functions (exactly the human proof, using ULift Bool as the two-element test object in the right universe) and once for Mathlib's bundled natural transformations.
/-- The **squaring functor** on types: `X ↦ X × X`, and a function `f : X → Y` acts on pairs
coordinatewise, `(a, b) ↦ (f a, f b)`. (In this Mathlib, morphisms in the category of types are
wrapped functions; `↾g` turns a function `g` into a morphism.) -/
def sq : Type u ⥤ Type u where
obj X := X × X
map f := ↾(Prod.map f f)/-- **Every natural family of maps `X × X → X` is a projection.** Suppose `α X : X × X → X` is
given for every type `X`, and is natural: `α Y (f a, f b) = f (α X (a, b))` for every function
`f : X → Y`. Then either `α X (a, b) = a` for all `X, a, b`, or `α X (a, b) = b` for all.
Proof (as in the lesson). Look at one test case: the pair `(true, false)` in the two-element type
`B`. For any `X` and `(a, b)`, the function `f : B → X` with `f true = a`, `f false = b` sends
`(true, false)` to `(a, b)`, so naturality gives `α X (a, b) = f (α B (true, false))`. Hence the
whole family is decided by one value, `α B (true, false)`, which is `true` (projection to `a`) or
`false` (projection to `b`). `ULift` moves `Bool` into the universe `u`. -/
theorem natural_sq_to_id (α : ∀ X : Type u, X × X → X)
(nat : ∀ (X Y : Type u) (f : X → Y) (p : X × X), α Y (f p.1, f p.2) = f (α X p)) :
(∀ (X : Type u) (p : X × X), α X p = p.1) ∨ (∀ (X : Type u) (p : X × X), α X p = p.2) := by
-- Every component is determined by the single value `α B (true, false)`.
have key : ∀ (X : Type u) (p : X × X),
α X p = (if (α (ULift.{u} Bool) (⟨true⟩, ⟨false⟩)).down then p.1 else p.2) := by
intro X p
have h := nat (ULift.{u} Bool) X (fun b => if b.down then p.1 else p.2) (⟨true⟩, ⟨false⟩)
simpa using h
rcases h : α (ULift.{u} Bool) (⟨true⟩, ⟨false⟩) with ⟨b⟩
cases b
· right
intro X p
rw [key, h]
rfl
· left
intro X p
rw [key, h]
rfl/-- The same theorem for Mathlib's bundled natural transformations: every `α : sq ⟶ 𝟭 (Type u)`
is the first or the second projection. The naturality square of `α` at `f`, applied to an
element (`NatTrans.naturality_apply`), is exactly the hypothesis of `natural_sq_to_id`. -/
theorem natTrans_sq_to_id (α : sq ⟶ 𝟭 (Type u)) :
(∀ (X : Type u) (p : X × X), α.app X p = p.1) ∨
(∀ (X : Type u) (p : X × X), α.app X p = p.2) := by
apply natural_sq_to_id (fun X => α.app X)
intro X Y f p
exact NatTrans.naturality_apply α (↾f) p/-- **The identity functor on types has only the identity as natural endo-transformation.**
If `α X : X → X` is natural, then for `x : X` take `f : PUnit → X` with value `x`; naturality
says `α X (f ()) = f (α PUnit ())`, and the right side is `x` whatever `α PUnit ()` is. -/
theorem natural_id_to_id (α : ∀ X : Type u, X → X)
(nat : ∀ (X Y : Type u) (f : X → Y) (x : X), α Y (f x) = f (α X x)) :
∀ (X : Type u) (x : X), α X x = x := by
intro X x
exact nat PUnit X (fun _ => x) PUnit.unit/-- Bundled form: the only natural transformation `𝟭 (Type u) ⟶ 𝟭 (Type u)` is the identity
`𝟙 _`, i.e. the endomorphism monoid of the identity functor on types is trivial. -/
theorem natTrans_id_eq (α : 𝟭 (Type u) ⟶ 𝟭 (Type u)) : α = 𝟙 _ := by
ext X x
exact natural_id_to_id (fun X => α.app X)
(fun X Y f x => by simpa using NatTrans.naturality_apply α (↾f) x) X xList reversal, as a natural transformation of Mathlib's list functor:
/-- **List reversal is a natural transformation** from the list functor to itself
(`ofTypeFunctor List` is Mathlib's functor `X ↦ List X`, acting on functions by `List.map`).
The naturality square says `reverse (map f xs) = map f (reverse xs)`: it does not matter whether
we relabel the entries before or after reversing. This is core Lean's `List.map_reverse`. -/
def reverseNat : ofTypeFunctor List ⟶ ofTypeFunctor List where
app X := ↾List.reverse
naturality X Y f := by
ext xs
exact (List.map_reverse ..).symmLinear algebra. The double-dual square holds by computation — after applying both sides to v and φ, Lean sees φ (f v) on each side and accepts rfl. Bijectivity in finite dimension is Mathlib's theorem. Then Theorem 5(b), in the form "a line over a field with a unit , , carries no nonzero automorphism-invariant pairing".
/-- **The double-dual map is natural.** `Module.Dual.eval R V : V → V**` sends `v` to
"evaluate at `v`", `φ ↦ φ v`. For every linear `f : V → W` the square
`f** ∘ ev_V = ev_W ∘ f` commutes: both sides send `v` and `φ ∈ W*` to `φ (f v)`, since
`f** (ev_V v) φ = ev_V v (f* φ) = (φ ∘ f) v`. Lean checks the two sides agree by computation
(`rfl`) after applying both to `v` and `φ`; Mathlib states the same fact as
`Module.Dual.eval_naturality`. -/
theorem double_dual_naturality {V W : Type u} [AddCommGroup V] [Module R V] [AddCommGroup W]
[Module R W] (f : V →ₗ[R] W) :
f.dualMap.dualMap ∘ₗ Module.Dual.eval R V = Module.Dual.eval R W ∘ₗ f := by
ext v φ
rfl/-- **In finite dimension the double-dual map is an isomorphism**, so `ev` is a natural
isomorphism from the identity functor to the double-dual functor on finite-dimensional spaces.
This applies Mathlib's `Module.bijective_dual_eval` (finite-dimensional spaces are reflexive).
Without finite dimension it fails: `ev` is still injective but no longer onto. -/
theorem double_dual_bijective {K V : Type u} [Field K] [AddCommGroup V] [Module K V]
[FiniteDimensional K V] : Function.Bijective (Module.Dual.eval K V) :=
Module.bijective_dual_eval K V/-- **A line has no automorphism-invariant pairing over a field with more than three elements.**
A natural isomorphism `V → V*` on the groupoid of vector spaces and linear isomorphisms would
give, for `V = K`, a linear map `φ : K → K*` with `φ (μ v) (μ w) = φ v w` for every unit `μ`
(see the lesson). If some unit `λ` has `λ² ≠ 1`, such a `φ` must be zero, so it is not an
isomorphism. Proof: by linearity `φ v w = v w · φ 1 1`; invariance under `λ` gives
`λ² · φ 1 1 = φ 1 1`, so `(λ² − 1) · φ 1 1 = 0` and `φ 1 1 = 0`. -/
theorem no_invariant_pairing {K : Type u} [Field K] (φ : K →ₗ[K] Module.Dual K K)
(hφ : ∀ (μ : Kˣ) (v w : K), φ (μ * v) (μ * w) = φ v w) (lam : Kˣ) (hlam : lam ^ 2 ≠ 1) :
φ = 0 := by
-- Step 1: `φ` is determined by the number `φ 1 1`.
have h1 : ∀ v w : K, φ v w = v * w * φ 1 1 := by
intro v w
have hv : φ v = v • φ 1 := by rw [← map_smul, smul_eq_mul, mul_one]
rw [hv, LinearMap.smul_apply, smul_eq_mul]
have hw : φ 1 w = w * φ 1 1 := by rw [← smul_eq_mul, ← map_smul, smul_eq_mul, mul_one]
rw [hw, mul_assoc]
-- Step 2: invariance under `λ` forces `φ 1 1 = 0`.
have h2 : φ 1 1 = 0 := by
have hinv := hφ lam 1 1
rw [h1, h1, mul_one, one_mul, one_mul] at hinv
have h3 : ((lam : K) * lam - 1) * φ 1 1 = 0 := by rw [sub_mul, hinv, one_mul, sub_self]
rcases mul_eq_zero.mp h3 with h | h
· exfalso
apply hlam
ext
rw [Units.val_pow_eq_pow_val, pow_two, Units.val_one]
exact sub_eq_zero.mp h
· exact h
refine LinearMap.ext fun v => LinearMap.ext fun w => ?_
rw [h1, h2, mul_zero]
rflThe determinant as an honest natural transformation between functors CommRingCat ⥤ GrpCat:
/-- The **general linear group functor** `GLₙ : CommRingCat ⥤ GrpCat`: a commutative ring `R`
goes to the group of invertible `n × n` matrices over `R`, and a ring homomorphism `f : R → S`
goes to the group homomorphism applying `f` to every entry (`Matrix.GeneralLinearGroup.map`). -/
noncomputable def glFunctor : CommRingCat.{u} ⥤ GrpCat.{u} where
obj R := GrpCat.of (Matrix.GeneralLinearGroup n R)
map f := GrpCat.ofHom (Matrix.GeneralLinearGroup.map f.hom)/-- The **units functor** `(−)ˣ : CommRingCat ⥤ GrpCat`: a ring goes to its group of units, a
ring homomorphism to its restriction to units (`Units.map`). -/
def unitsFunctor : CommRingCat.{u} ⥤ GrpCat.{u} where
obj R := GrpCat.of Rˣ
map f := GrpCat.ofHom (Units.map f.hom.toMonoidHom)/-- **The determinant is natural in the ring.** Its components are the group homomorphisms
`det : GLₙ(R) → Rˣ`; the naturality square for `f : R → S` says
`det (f(M)) = f (det M)`: applying `f` to the entries and then taking the determinant gives the
same as taking the determinant and then applying `f`, because the determinant is a polynomial
in the entries with integer coefficients. This is Mathlib's `Matrix.GeneralLinearGroup.map_det`. -/
noncomputable def detNat : glFunctor.{u} n ⟶ unitsFunctor.{u} where
app R := GrpCat.ofHom Matrix.GeneralLinearGroup.det
naturality R S f := by
ext g
exact Matrix.GeneralLinearGroup.map_det f.hom gThe functor category (Theorems 1 and 2) is built into Mathlib:
/-- **Vertical composition is computed componentwise.** In the functor category `C ⥤ D`
(Mathlib's instance `Functor.category`), the composite of `α : F ⟶ G` and `β : G ⟶ H` has
components `(α ≫ β).app X = α.app X ≫ β.app X`. This applies Mathlib's `NatTrans.comp_app`. -/
theorem comp_app {F G H : C ⥤ D} (α : F ⟶ G) (β : G ⟶ H) (X : C) :
(α ≫ β).app X = α.app X ≫ β.app X :=
NatTrans.comp_app α β X/-- **A natural transformation whose components are isomorphisms is a natural isomorphism**:
it is invertible in the functor category, because the inverse components are automatically
natural. This applies Mathlib's `NatIso.isIso_of_isIso_app`. -/
theorem isIso_of_components {F G : C ⥤ D} (α : F ⟶ G) [∀ X : C, IsIso (α.app X)] : IsIso α :=
NatIso.isIso_of_isIso_app αEquivalences (Theorem 6). The three parts of () are proved by hand, following the proof above; note how full_of_equivalence reuses faithful_of_unitIso for , exactly as the human proof says "by symmetry". The () direction is Mathlib's Functor.asEquivalence, which uses choice (Functor.objPreimage).
/-- **A functor with a quasi-inverse is faithful.** If `η : 𝟭 C ≅ F ⋙ G`, then naturality of `η`
lets us recover every morphism `k : X ⟶ Y` from `F.map k`:
`k = η_X ≫ G.map (F.map k) ≫ η_Y⁻¹` (diagrammatic order: first `η_X`). So `F.map f = F.map g`
forces `f = g`. -/
theorem faithful_of_unitIso (F : C ⥤ D) (G : D ⥤ C) (η : 𝟭 C ≅ F ⋙ G) : F.Faithful where
map_injective {X Y} {f g} h := by
have key : ∀ k : X ⟶ Y, k = η.hom.app X ≫ G.map (F.map k) ≫ η.inv.app Y := by
intro k
calc k = k ≫ η.hom.app Y ≫ η.inv.app Y := by simp
_ = (k ≫ η.hom.app Y) ≫ η.inv.app Y := by rw [Category.assoc]
_ = (η.hom.app X ≫ G.map (F.map k)) ≫ η.inv.app Y := by
rw [show k ≫ η.hom.app Y = η.hom.app X ≫ G.map (F.map k) from η.hom.naturality k]
_ = η.hom.app X ≫ G.map (F.map k) ≫ η.inv.app Y := by rw [Category.assoc]
rw [key f, key g, h]/-- **A functor with a quasi-inverse is essentially surjective**: every object `Y` of `D` is
isomorphic to `F (G Y)`, by the component `ε_Y` of `ε : G ⋙ F ≅ 𝟭 D`. -/
theorem essSurj_of_counitIso (F : C ⥤ D) (G : D ⥤ C) (ε : G ⋙ F ≅ 𝟭 D) : F.EssSurj where
mem_essImage Y := ⟨G.obj Y, ⟨ε.app Y⟩⟩/-- **A functor with a quasi-inverse is full.** Given `h : F X ⟶ F Y`, put
`f = η_X ≫ G.map h ≫ η_Y⁻¹ : X ⟶ Y`. Naturality of `η` gives `G.map (F.map f) = G.map h`, and
`G` is faithful (by `faithful_of_unitIso` applied to `G`, with `ε⁻¹ : 𝟭 D ≅ G ⋙ F`), so
`F.map f = h`. This is the proof in the lesson, step by step. -/
theorem full_of_equivalence (F : C ⥤ D) (G : D ⥤ C) (η : 𝟭 C ≅ F ⋙ G)
(ε : G ⋙ F ≅ 𝟭 D) : F.Full where
map_surjective {X Y} h := by
have hG : G.Faithful := faithful_of_unitIso G F ε.symm
refine ⟨η.hom.app X ≫ G.map h ≫ η.inv.app Y, G.map_injective ?_⟩
-- Naturality of `η` at `f`: `f ≫ η_Y = η_X ≫ G.map (F.map f)`.
have hnat := η.hom.naturality (η.hom.app X ≫ G.map h ≫ η.inv.app Y)
simp only [Functor.id_map, Functor.comp_map, Functor.id_obj] at hnat
calc G.map (F.map (η.hom.app X ≫ G.map h ≫ η.inv.app Y))
= η.inv.app X ≫ η.hom.app X ≫ G.map (F.map (η.hom.app X ≫ G.map h ≫ η.inv.app Y)) := by
simp
_ = η.inv.app X ≫ (η.hom.app X ≫ G.map h ≫ η.inv.app Y) ≫ η.hom.app Y := by rw [hnat]
_ = G.map h := by simp/-- **Characterisation of equivalences.** A functor `F` has a quasi-inverse `G` (with natural
isomorphisms `𝟭 C ≅ F ⋙ G` and `G ⋙ F ≅ 𝟭 D`) if and only if it is full, faithful and
essentially surjective. (→) is `Functor.IsEquivalence.mk'` (the three lemmas above prove it by
hand). (←) is Mathlib's `Functor.asEquivalence`, which *chooses* for each object `Y` of `D` an
object `X` with `F X ≅ Y` — this direction uses the axiom of choice. -/
theorem equivalence_iff (F : C ⥤ D) :
(∃ G : D ⥤ C, Nonempty (𝟭 C ≅ F ⋙ G) ∧ Nonempty (G ⋙ F ≅ 𝟭 D)) ↔
F.Full ∧ F.Faithful ∧ F.EssSurj := by
constructor
· rintro ⟨G, ⟨η⟩, ⟨ε⟩⟩
have := Functor.IsEquivalence.mk' G η ε
exact ⟨inferInstance, inferInstance, inferInstance⟩
· rintro ⟨h₁, h₂, h₃⟩
have : F.IsEquivalence := {}
exact ⟨F.inv, ⟨F.asEquivalence.unitIso⟩, ⟨F.asEquivalence.counitIso⟩⟩Finally, equivalent need not mean isomorphic: two isomorphic objects form a category equivalent to the one-object category, but no isomorphism of categories exists.
/-- **Two isomorphic objects are "the same" as one object.** `Codiscrete Bool` is the category
with two objects and exactly one morphism between any two (so the two objects are isomorphic);
`Codiscrete Unit` has one object and only its identity. Collapsing and picking an object are
quasi-inverse functors: any two functors into a codiscrete category are naturally isomorphic
(Mathlib's `Codiscrete.natIso`). -/
def codiscreteEquivalence : Codiscrete Bool ≌ Codiscrete Unit :=
CategoryTheory.Equivalence.mk (Codiscrete.functorOfFun fun _ => ())
(Codiscrete.functorOfFun fun _ => true) Codiscrete.natIso Codiscrete.natIso/-- **Equivalent categories need not be isomorphic.** There are no functors
`F : Codiscrete Bool ⥤ Codiscrete Unit` and `G` back with `F ⋙ G = 𝟭` (on the nose): `F` would
have to be injective on objects, but it sends both objects to the only object. -/
theorem codiscrete_not_isomorphic :
¬ ∃ (F : Codiscrete Bool ⥤ Codiscrete Unit) (G : Codiscrete Unit ⥤ Codiscrete Bool),
F ⋙ G = 𝟭 _ ∧ G ⋙ F = 𝟭 _ := by
rintro ⟨F, G, h, -⟩
have h1 : G.obj (F.obj ⟨true⟩) = ⟨true⟩ := congrArg (fun H => H.obj ⟨true⟩) h
have h2 : G.obj (F.obj ⟨false⟩) = ⟨false⟩ := congrArg (fun H => H.obj ⟨false⟩) h
have hU : ∀ a b : Codiscrete Unit, a = b := fun ⟨()⟩ ⟨()⟩ => rfl
rw [hU (F.obj ⟨true⟩) (F.obj ⟨false⟩), h2] at h1
exact Bool.false_ne_true (congrArg Codiscrete.as h1)What is not formalised here: the equivalence , the failure of surjectivity of in infinite dimension, and Theorem 5(b) for the full groupoid (we formalise its key step, the computation on a line).
Experiments: symmetry is not naturality
Theorem 3 says that only the projections are natural maps . The first experiment searches all tables on a two-element set and all tables on a three-element set. Asking only for compatibility with bijections — symmetry — leaves a third operation on : and "the third element". Compatibility with all functions rules it out, and the experiment prints a non-injective map whose square fails. Naturality is stronger than symmetry precisely because it must commute with maps that identify elements.
"""Which ways of combining two elements of a set work for every set at once?
A family of maps alpha_X : X x X -> X, one for each set X, is natural when
alpha_Y(f(a), f(b)) = f(alpha_X(a, b)) for every function f : X -> Y. The
lesson proves that the only natural families are the two projections. Here we
search exhaustively on the finite sets {0, 1} and {0, 1, 2}: first for tables
that commute with every bijection of the set (symmetry), then for tables that
commute with every function from the set to itself (a necessary condition for
naturality). Symmetry alone allows a third operation; the functions kill it,
and we print a square that fails.
"""
from itertools import permutations, product
def all_tables(n):
"""Every map n x n -> n, as a tuple t with t[a * n + b] = alpha(a, b)."""
return product(range(n), repeat=n * n)
def all_maps(m, n):
"""Every function {0..m-1} -> {0..n-1}, as a tuple of values."""
return list(product(range(n), repeat=m))
def commutes(t_src, t_dst, f, m, n):
"""Does the square for f : m -> n commute: t_dst(f a, f b) = f(t_src(a, b))?"""
return all(t_dst[f[a] * n + f[b]] == f[t_src[a * m + b]]
for a in range(m) for b in range(m))
def natural_tables(n, maps):
"""Tables on n commuting with every endomap in ``maps`` (an exhaustive search)."""
return [t for t in all_tables(n)
if all(commutes(t, t, f, n, n) for f in maps)]
def projection(n, k):
"""The k-th projection n x n -> n (k = 0: first, k = 1: second)."""
return tuple((a, b)[k] for a in range(n) for b in range(n))
def third_element(t):
"""On {0, 1, 2}: is t the operation (a, a) -> a, (a, b) -> the third element?"""
want = tuple(a if a == b else 3 - a - b for a in range(3) for b in range(3))
return t == want
def breaking_square(t, n=3):
"""The first endomap f of {0..n-1} and pair (a, b) where the square fails,
as (f, a, b, alpha(f a, f b), f(alpha(a, b))); None if t is natural."""
for f in all_maps(n, n):
for a in range(n):
for b in range(n):
lhs, rhs = t[f[a] * n + f[b]], f[t[a * n + b]]
if lhs != rhs:
return f, a, b, lhs, rhs
return None
def main():
print("Tables alpha : X x X -> X, searched exhaustively.")
for n in (2, 3):
bij = [tuple(p) for p in permutations(range(n))]
sym = natural_tables(n, bij)
nat = natural_tables(n, all_maps(n, n))
print(f"|X| = {n}: {n ** (n * n):>5} tables, {len(sym)} commute with all "
f"{len(bij)} bijections, {len(nat)} with all {n ** n} self-maps")
sym3 = natural_tables(3, [tuple(p) for p in permutations(range(3))])
nat3 = natural_tables(3, all_maps(3, 3))
projections = {projection(3, 0), projection(3, 1)}
print(f"On 3 elements the natural tables are the projections: "
f"{set(nat3) == projections}")
extra = [t for t in sym3 if t not in projections]
print(f"The symmetric extra table is 'the third element': "
f"{len(extra) == 1 and third_element(extra[0])}")
f, a, b, lhs, rhs = breaking_square(extra[0])
print(f"Its square fails for f = {f} (i -> f[i]) at the pair ({a}, {b}):")
print(f" alpha(f({a}), f({b})) = alpha({f[a]}, {f[b]}) = {lhs}, but "
f"f(alpha({a}, {b})) = f({extra[0][a * 3 + b]}) = {rhs}.")
print("f is not injective: symmetry alone cannot see this failure.")
print()
print("Epistemic status: an exhaustive search over all 16 and 19,683 tables on")
print("sets of sizes 2 and 3 - complete for those sizes, silent about larger")
print("sets. That only the projections are natural on all sets is proved in")
print("the lesson (and in Lean), using one test pair in a two-element set.")
if __name__ == "__main__":
main()The second experiment studies Theorem 5(b) over small prime fields: it counts the non-degenerate bilinear forms on that are invariant under every invertible matrix, and finds the exceptional cases over and that the theorem's hypothesis "more than three elements" leaves open.
"""Is there a natural isomorphism V -> V*? Small finite fields answer.
The dual space construction is contravariant, so "V is naturally isomorphic
to V*" cannot even be stated for all linear maps. On the groupoid of
isomorphisms it can be: a natural isomorphism amounts to a non-degenerate
bilinear form B on each space with B(gv, gw) = B(v, w) for every invertible g,
i.e. g^T B g = B. We count such forms on F_p^n for small p and n by exhaustive
search, testing invariance on a generating set of GL_n(F_p). We also count how
many invertible maps preserve the dot product, the pairing a basis gives.
"""
from itertools import product
def mat_mul(a, b, p):
"""Product of square matrices (tuples of row tuples) over F_p."""
n = len(a)
return tuple(tuple(sum(a[i][k] * b[k][j] for k in range(n)) % p
for j in range(n)) for i in range(n))
def transpose(a):
"""The transpose of a square matrix."""
return tuple(zip(*a))
def det(a, p):
"""Determinant over F_p by Laplace expansion (fine for n <= 3)."""
n = len(a)
if n == 1:
return a[0][0] % p
total = 0
for j in range(n):
minor = tuple(row[:j] + row[j + 1:] for row in a[1:])
total += (-1) ** j * a[0][j] * det(minor, p)
return total % p
def all_matrices(n, p):
"""Every n x n matrix over F_p."""
for entries in product(range(p), repeat=n * n):
yield tuple(tuple(entries[i * n:(i + 1) * n]) for i in range(n))
def primitive_root(p):
"""The least generator of the multiplicative group of F_p."""
for g in range(1, p):
if len({pow(g, k, p) for k in range(1, p)}) == p - 1:
return g
raise ValueError("p must be prime")
def gl_generators(n, p):
"""Transvections I + E_ij (i != j) and diag(g, 1, ..., 1), g a primitive
root: a standard generating set of GL_n(F_p)."""
ident = [[int(i == j) for j in range(n)] for i in range(n)]
gens = []
for i, j in product(range(n), repeat=2):
if i != j:
m = [row[:] for row in ident]
m[i][j] = 1
gens.append(tuple(map(tuple, m)))
d = [row[:] for row in ident]
d[0][0] = primitive_root(p)
gens.append(tuple(map(tuple, d)))
return gens
def invariant(b, g, p):
"""Is the bilinear form with Gram matrix b preserved by g: g^T b g = b?"""
return mat_mul(mat_mul(transpose(g), b, p), g, p) == b
def invariant_forms(n, p):
"""Non-degenerate forms on F_p^n preserved by every element of GL_n(F_p)."""
gens = gl_generators(n, p)
return [b for b in all_matrices(n, p)
if det(b, p) and all(invariant(b, g, p) for g in gens)]
def dot_preserving(n, p):
"""(number of invertible g with g^T g = I, size of GL_n(F_p))."""
ident = tuple(tuple(int(i == j) for j in range(n)) for i in range(n))
invertible = [g for g in all_matrices(n, p) if det(g, p)]
keep = [g for g in invertible if invariant(ident, g, p)]
return len(keep), len(invertible)
def main():
print("Non-degenerate bilinear forms on F_p^n fixed by all of GL_n(F_p):")
for p, n in [(2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (5, 1), (5, 2)]:
forms = invariant_forms(n, p)
shown = " ".join(str([list(r) for r in b]) for b in forms) or "none"
print(f" p = {p}, n = {n}: {len(forms)} {shown}")
print("Over F_5 the scalar 2 has 2^2 = 4 != 1, so even a line has none;")
print("on F_2^2 the survivor is the determinant pairing, as det(g) = 1.")
print()
print("The dot product (a basis-made pairing) is preserved only by")
for p, n in [(2, 2), (3, 2), (5, 2)]:
keep, total = dot_preserving(n, p)
print(f" {keep:>2} of the {total:>3} invertible maps of F_{p}^{n}")
print()
print("Epistemic status: exact, exhaustive computation for the listed p and n,")
print("relying on the standard theorem that transvections and one diagonal")
print("matrix generate GL_n(F_p). It proves nothing about other fields or")
print("dimensions. The lesson proves that over every field with more than")
print("three elements even a line has no invariant pairing, so V -> V* is")
print("not natural even on the groupoid of isomorphisms.")
if __name__ == "__main__":
main()Explore: which pairings survive a change of basis?
A natural isomorphism on the groupoid would be a pairing preserved by every invertible linear map. Try the presets below on the plane . A shear has determinant : it preserves area — the pairing — but changes lengths and angles, so it does not preserve the dot product. So does the preset scaling (factors and ). A rotation preserves both the dot product and the area; a reflection preserves the dot product but reverses the sign of the area. Finally edit the entries to the uniform scaling : it multiplies every bilinear form by , so no non-zero pairing survives all invertible maps — the plane version of Theorem 5(b).
Invariant pairings under change of basis
Shears keep area, rotations keep the dot product, scalings keep neither.
- image of the grid
- image of the unit square
- image of the flag
- before the transformation
- invariant line
The columns of A are the images of e₁ = (1, 0) and e₂ = (0, 1): Ae₁ = (1, 0), Ae₂ = (1, 1)
det A = ad − bc = 1
The unit square (area 1) becomes a parallelogram of area |det A| = 1. Since det A > 0, orientation is preserved.
Invariant lines (real eigenvectors)
λ = 1, v = (1, 0)
Only one invariant line, with eigenvalue 1: there is no second eigenvector direction.
Exercises
1. Natural transformations
Warm-upHumanLet be functors and a family of morphisms. Which equation must hold for every for to be natural?
2. Natural transformations
CoreHumanLet be the functor , . How many natural transformations are there?
3. Natural transformations
CoreHumanWhich of these families are natural transformations (between the functors indicated)? Select all that apply.
4. Natural transformations
CoreHumanLet be a natural transformation with . What is ? Give the representative in .
5. Natural transformations
CoreHumanIn the proof that an equivalence (with , ) is full, we set for a given and showed . What is needed to conclude ?
6. Natural transformations
StretchHumanWhich statement about on the category of all vector spaces over a field is true?
7. Natural transformations
CoreFormalMathlib writes composition in diagrammatic order: f ≫ g means “first f, then g”. For α : F ⟶ G between functors C ⥤ D and f : X ⟶ Y in C, which Lean statement is the naturality square?
8. Natural transformations
StretchHumanWhich pairs of categories are equivalent? Select all that apply.
9. Natural transformations
StretchComputationalA binary operation on is stored as a tuple t with t[a * n + b] . Write natural_tables(n) returning the list of all such tables that commute with every function , i.e. t[f[a] * n + f[b]] == f[t[a * n + b]] for all (with f a tuple of values). Theorem 3 predicts the answer.
Common misconceptions
Misconception
"Natural" means "obvious" or "canonical-looking". Naturality is a precise condition: a family of morphisms, indexed by objects, making every naturality square commute. Some canonical-looking maps are not natural (the inclusions of centres are natural only for isomorphisms: is not even a functor on ), and some natural transformations look surprising (the two projections are the only natural maps , but both are equally natural — naturality does not single out one).
Misconception
"Equivalent categories are isomorphic." An equivalence only requires and , up to natural isomorphism. and are equivalent but not isomorphic; a category with two isomorphic objects (and one arrow between any two objects) is equivalent to the one-object category but has a different number of objects. Equivalence ignores exactly the information — how many copies of each isomorphism class — that categorical constructions cannot detect.
Misconception
"A natural transformation with injective (or bijective) components is all you need for an isomorphism of whatever you care about." The double-dual map is natural with injective components on all of , but it is a natural isomorphism only on finite-dimensional spaces. Naturality and invertibility are independent requirements.
Misconception
"If each is isomorphic to , then ." Objectwise isomorphisms need not assemble into a natural one. On finite-dimensional spaces, for every , yet (Theorem 5) there is no natural isomorphism, even on the groupoid of isomorphisms over . The isomorphisms must be chosen compatibly with all arrows.
Viewpoints
Topology— Natural transformations are homotopies
Let . A natural transformation between functors is the same thing as a functor with and — compare a homotopy between maps and . This is more than an analogy: under the classifying-space construction (the geometric realisation of the nerve), becomes the interval, and a natural transformation induces a homotopy (Segal, 1968). In particular an equivalence of categories induces a homotopy equivalence of classifying spaces.
Historically the influence ran the other way. In algebraic topology homology is a functor, the connecting maps of the long exact sequence are natural, and the Hurewicz map is natural. The universal coefficient theorem gives isomorphisms that split non-naturally: the short exact sequence behind them is natural in , but no splitting can be chosen naturally. Making such distinctions precise was exactly Eilenberg and Mac Lane's goal.
Geometry— Klein's principle and the musical isomorphism
Klein's Erlangen programme studies a geometry through the quantities invariant under its symmetry group. Naturality is the same idea with a groupoid (or a category) of symmetries: a construction is natural for a class of maps when it commutes with all of them. On a smooth manifold , the tangent bundle and cotangent bundle are both functorial (for diffeomorphisms), canonically, but an identification — the "musical isomorphism" of Riemannian geometry — requires a metric , and it is natural only for isometries. This is Theorem 5 in geometric dress: a pairing is a geometric structure, and only the maps preserving it see the identification as natural.
The exceptional pairing on is geometric too: is the area form (a symplectic form), preserved exactly by the maps of determinant , . Over every invertible matrix has determinant , so area is preserved by everything.
Algebra— Determinants, abelianisation and Morita equivalence
Algebra is full of natural transformations: the determinant ; abelianisation ; the canonical map of modules; the inclusion of a module into its double dual. The test-object computation above shows that the natural endomorphisms of form the ring , and more generally the natural endomorphisms of the identity functor of form the centre .
Equivalence of categories gives algebra a coarser and more useful notion of sameness for rings. Morita's theorem (Kiiti Morita, 1958): for every ring and , the categories of left modules over and over the matrix ring are equivalent, although the rings are not isomorphic. Properties that depend only on the module category — being semisimple, Noetherian, the centre, the lattice of two-sided ideals — are therefore shared by and .
Computation— Theorems for free
In a typed functional language, a function of type ∀ a. List a → List a cannot inspect the elements it is given — it does not know their type — so it can only rearrange, copy or drop them by position. Reynolds' parametricity theorem (1983) makes this precise, and Wadler's "Theorems for free!" (1989) draws the consequence: every such function commutes with map f, i.e. it is a natural transformation of the list functor. A function of type ∀ a. (a, a) → a must be fst or snd — the programming counterpart of Theorem 3(a). The two statements have different hypotheses (parametricity is a property of the terms of a language, naturality a property of a family of maps), but they express the same uniformity, and the first computation above shows that symmetry alone is not enough to obtain it.
Category theory— A 2-category, and the Yoneda lemma
Categories, functors and natural transformations form a 2-category : besides vertical composition, transformations (for ) and (for ) have a horizontal composite , , and the two compositions satisfy the interchange law. Equivalence is the notion of isomorphism appropriate to a 2-category. The "test object" proofs above are instances of the Yoneda lemma: , so has exactly two elements, the two projections. Natural transformations are also the raw material of adjunctions and limits: a cone is a natural transformation from a constant functor.
Wonder Trails
History and global context
- Samuel Eilenberg (born in Warsaw, trained in the Polish school of topology) and Saunders Mac Lane (USA) began collaborating in the early 1940s on group extensions and their role in the homology of spaces (the groups now called ). Their 1942 note "Natural isomorphisms in group theory" and their 1945 paper "General theory of natural equivalences" introduced categories, functors and natural transformations, with the double dual as a leading example. Mac Lane later wrote that "category" was defined in order to define "functor", and "functor" in order to define "natural transformation".
- Dualities that are now read as equivalences of categories predate the language: Lev Pontryagin's duality for locally compact abelian groups (1934), Marshall Stone's representation of Boolean algebras by spaces (1936), and Israel Gelfand and Mark Naimark's theorem (1943) identifying commutative C*-algebras with algebras of functions on compact Hausdorff spaces.
- In the 1950s equivalences became a working tool: Kiiti Morita (1958) characterised when module categories over two rings are equivalent, and Alexander Grothendieck's work in homological algebra and algebraic geometry made "up to equivalence" the default way to compare categories. Daniel Kan's 1958 paper on adjoint functors, the next lesson in this sequence, is built on natural transformations throughout.
Further reading
- Saunders Mac Lane, Categories for the Working Mathematician (1971; 2nd edition 1998), Chapters I and IV.3–4 — the classic, by one of the founders.
- Emily Riehl, Category Theory in Context (2016), Sections 1.4–1.5 — natural transformations and equivalences, with many examples.
- Tom Leinster, Basic Category Theory (2014), Chapter 1 — a gentle, precise first course.
- Steve Awodey, Category Theory (2nd edition, 2010), Chapter 7.
- Samuel Eilenberg and Saunders Mac Lane, "General theory of natural equivalences", Transactions of the AMS 58 (1945) — the founding paper, still readable.
- Philip Wadler, "Theorems for free!", Functional Programming Languages and Computer Architecture (1989) — naturality from parametricity.
- T. Y. Lam, Lectures on Modules and Rings (1999), Chapter 7 — Morita equivalence.