mirror of
https://github.com/Smaug123/static-site-pipeline
synced 2025-10-05 16:28:41 +00:00
149 lines
16 KiB
Markdown
149 lines
16 KiB
Markdown
---
|
|
lastmod: "2024-04-13T16:58:00.0000000+01:00"
|
|
author: patrick
|
|
date: "2024-04-13T16:58:00.0000000+01:00"
|
|
title: The Yoneda lemma
|
|
summary: "Another attempt to explain that the Yoneda lemma is actually intuitive."
|
|
math: true
|
|
---
|
|
|
|
*Read this post with a pencil and paper! Draw pictures!*
|
|
|
|
# What is a diagram?
|
|
|
|
A functor \\(\mathcal{C} \to \mathcal{D}\\) is basically a way of identifying a copy of \\(\mathcal{C}\\) inside \\(\mathcal{D}\\).
|
|
That is, it's a specification of an object of \\(\mathcal{D}\\) for every object of \\(\mathcal{C}\\), and corresponding morphisms inside \\(\mathcal{D}\\) which must go between the right objects for this to be a copy of \\(\mathcal{C}\\).
|
|
|
|
If we specialise to the category of sets, a functor \\(\mathcal{C} \to \mathrm{\mathbf{Set}}\\) is a set for every object of \\(\mathcal{C}\\), and functions between those objects.
|
|
|
|
Imagine \\(\mathcal{C}\\) as some kind of abstract template of a universe of types; then a functor \\(\mathcal{C} \to \mathrm{\mathbf{Set}}\\) is an *instantation* of that universe of types.
|
|
For example, perhaps we decide that this particular object of \\(\mathcal{C}\\) will be instantiated to \\(\mathbb{N}\\), and that particular object will be instantiated to \\(\mathrm{Bool}\\), and this arrow between them will be instantiated to \\(n \mapsto \mathrm{isEven}(n)\\).
|
|
|
|
Recall what the functor laws in this context are:
|
|
|
|
* The functor respects endpoints of morphisms: if \\(f: A \to B\\) in \\(\mathcal{C}\\), then \\(Ff : FA \to FB\\) in \\(\mathrm{\mathbf{Set}}\\). That is, we really are identifying a copy of \\(\mathcal{C}\\) in \\(\mathrm{\mathbf{Set}}\\): we're not actively breaking the structure in translation. If the template \\(\mathcal{C}\\) tells us how to get from \\(A\\) to \\(B\\), then we can do that in our instantiation.
|
|
* The identity morphism is always taken to the identity function. (This one's fairly self-explanatory.)
|
|
* The functor respects compositions: \\(F(g \circ f) = F(g) \circ F(f)\\). That is, if the template tells us we can do \\(f\\) then \\(g\\), we can also do that in our instantiation; moreover, if our template tells us two paths are equal, then they're also equal in the instantiation.
|
|
|
|
Note what we're *not* requiring of our instantiations: that they're somehow "fully preserving all the structure".
|
|
If \\(\mathcal{C}\\) has two objects \\(A\\) and \\(B\\), we're perfectly happy to instantiate both of them to the same type, as long as all the arrows keep composing correctly.
|
|
In particular, for example, our instantiation might squash away arbitrarily much of the category's structure: every category has a trivial instantiation to the universe where there's only one set \\(\emptyset\\), and only one arrow \\(\mathrm{id} : \emptyset \to \emptyset\\).
|
|
|
|
# Homomorphisms between diagrams
|
|
|
|
Thinking of a diagram as some kind of instantiation of an abstract template, we can define homomorphisms (that is, structure-preserving maps) between them.
|
|
The concrete example of the "trivial instantiation" in the previous section may help you imagine how these homomorphisms should work.
|
|
|
|
If we have two diagrams \\(F, G : \mathcal{C} \to \mathrm{\mathbf{Set}}\\), we can define some particular homomorphism \\(\alpha\\) from the \\(F\\)-instantiation to the \\(G\\)-instantiation by sending every concrete \\(F\\)-type to a corresponding concrete \\(G\\)-type.
|
|
In order to deserve the name "homomorphism", it had better preserve the structure: that is, if \\(x : FA \to FB\\) is a function in our concrete instantiation of \\(\mathcal{C}\\), then it had better be the case that our homomorphism \\(\alpha\\) takes \\(x\\) to a suitable corresponding function \\(GA \to GB\\) in the \\(G\\)-instantiation.
|
|
|
|
In fact, every function in the \\(F\\)-instantiation is an image of a morphism from \\(\mathcal{C}\\) (that is, we defined our instantiations so that we weren't considering any extraneous functions there might be between the sets), so instead of considering the set of all general \\(x : FA \to FB\\), we only need to consider the set of all \\(Ff : FA \to FB\\).
|
|
Similarly, the functions \\(GA \to GB\\) are all of the form \\(Gg : GA \to GB\\) for some morphism \\(g\\) of \\(\mathcal{C}\\).
|
|
|
|
That is, a homomorphism from diagram \\(F\\) to diagram \\(G\\) is:
|
|
|
|
* an assignment, for each \\(A : |\mathcal{C}|\\), of some \\(GX\\) corresponding to \\(FA\\) (but note that in fact this \\(GX\\) must be \\(GA\\) to meet the later requirements, so there was no choice of target here);
|
|
* an assignment, for each \\(\mathcal{C}\\)-morphism \\(f : A \to B\\), of some \\(Gg\\) corresponding to \\(Ff\\) (but note that this must be \\(Gf\\) to meet the later requirements, so similarly there's no choice of target here);
|
|
* proofs that the homomorphism respects the basic structure of the category: if \\(f : A \to B\\) in \\(\mathcal{C}\\), then the map \\(Ff : FA \to FB\\) gets taken to the map \\(Gf : GA \to GB\\);
|
|
* proofs that the homomorphism "respects moving around within the diagram": "moving around in \\(F\\) and then taking the homomorphism over to \\(G\\)" should be the same as "taking the homomorphism to \\(G\\) and then making the same movement in \\(G\\)".
|
|
|
|
The homomorphism \\(\alpha\\) is pretty constrained: the only freedom is to decide exactly *how* \\(\alpha\\) sends \\(FA\\) to \\(GA\\) for each \\(A : |\mathcal{C}|\\).
|
|
|
|
We have a special name for these structure-preserving maps between diagrams: we call them *natural transformations*.
|
|
They provide us with a way of mapping between instantiations of the abstract theory specified by \\(\mathcal{C}\\).
|
|
|
|
# There are some very special examples of diagrams
|
|
|
|
We saw already that there are some pretty degenerate diagrams: the one which has every object going to the empty set, for instance.
|
|
That diagram has somehow "thrown away all the information" from the category.
|
|
|
|
Diagrams can also be pretty complex.
|
|
For example, take the diagrams for the very simple category that contains just one object and one arrow.
|
|
Literally every set in the universe (together with the corresponding identity function on that set) is a diagram for this category!
|
|
Most of those diagrams involve us ignoring tons of structure.
|
|
|
|
For example, there are \\(\mathbb{R}\\)-many functions \\(\mathbb{N} \to \mathbb{N}\\), so we're having to ignore uncountably many functions in the category of sets if we take the diagram consisting of "\\(\mathbb{N}\\) and its sole identity function".
|
|
This diagram wants to have way more structure than there was in \\(\mathcal{C}\\), and it's only by shutting our eyes and ignoring the set-structure we don't care about that we recover anything that looks remotely like \\(\mathcal{C}\\)!
|
|
|
|
It turns out there's a sweet spot of diagrams with "exactly the amount of structure \\(\mathcal{C}\\) specified, and no more".
|
|
The construction is: start with only one element in \\(FA\\) (for some \\(A\\)), and then chase through everything else that \\(\mathcal{C}\\) says should exist (which may involve adding in more elements of \\(FA\\) if there are morphisms telling us there should be more).
|
|
|
|
What does \\(\mathcal{C}\\) say should exist?
|
|
If \\(f : A \to B\\) is a morphism of \\(\mathcal{C}\\), and if \\(a \in FA\\) is an element of our concrete instantiation of the object \\(A\\), we really want there to be a distinct object \\((Ff)(a) \in FB\\) so that we've preserved the information "\\(f\\) was a morphism \\(A \to B\\)".
|
|
(If there weren't any such member of \\(FB\\), then our diagram has lost information: we might not be able to distinguish any more whether there was a morphism \\(f\\) in \\(\mathcal{C}\\) or not, just by looking at our instantiation \\(F\\).)
|
|
|
|
So if we assume there's an element \\(a \in FA\\), then for every \\(B \in |\mathcal{C}|\\), we can deduce the existence of elements \\((Ff)(a) \in B\\) for every \\(f : A \to B\\) in \\(\mathcal{C}\\); and they'd better all be distinct if we couldn't prove them to be equal in \\(\mathcal{C}\\).
|
|
|
|
Formally: for each object \\(A\\) of \\(\mathcal{C}\\), we can define a diagram \\(\mathrm{Rep}_A : \mathcal{C} \to \mathrm{\mathbf{Set}}\\) given by sending each \\(B\\) to the set of all morphisms in \\(\mathcal{C}\\) which go from \\(A\\) to \\(B\\).
|
|
This somehow "captures exactly all the structure that \\(\mathcal{C}\\) said \\(A\\) has".
|
|
(I've used the symbol \\(\mathrm{Rep}\\) to denote these diagrams, because the category-theoretic term for a diagram isomorphic to one of these is "*representable functor*".)
|
|
|
|
Note that I haven't yet written down the functions in these concrete instantiations of \\(\mathcal{C}\\); there's only one thing it could plausibly be.
|
|
Given \\(f : B \to C\\) a morphism of \\(\mathcal{C}\\), the corresponding function \\(\mathrm{Rep}_A(f) : \mathrm{Rep}_A(B) \to \mathrm{Rep}_A(C)\\) (that is, the function \\(\mathrm{Rep}_A(f) : \langle \text{morphisms $A \to B$ in $\mathcal{C}$} \rangle \to \langle\text{morphisms $A \to C$ in $\mathcal{C}$}\rangle\\) is defined to be given by composing with \\(f\\): we send \\(g : A \to B\\) to \\(f \circ g : A \to C\\).
|
|
|
|
These particular diagrams, the *representable functors* (one for every object in \\(\mathcal{C}\\)), together tell you everything there is to know about the category.
|
|
(That is kind of intuitive, by their definition as "the sets of morphisms": we can list out every morphism in the category, just by writing down every element of every object in each of these concrete instantiations.)
|
|
What might be less intuitive and requires a bit more thinking is their characterisation as "define \\(F\\) by supposing there's some single member \\(a \in FA\\), and then seeing what else is forced to exist"; you might find it helps to write out a concrete example of performing this operation for some particular tiny categories.
|
|
|
|
# Homomorphisms of the representable functors
|
|
|
|
The representable functors contain so little structure that their homomorphisms are forced to be quite simple.
|
|
|
|
Given any diagram \\(G : \mathcal{C} \to \mathrm{\mathbf{Set}}\\), and given any \\(A \in |\mathcal{C}|\\), we can precisely characterise the homomorphisms \\(\mathrm{Rep}_A \to G\\).
|
|
Remember, \\(\mathrm{Rep}_A\\) was defined by supposing there's just one "free generator" element \\(a \in \mathrm{Rep}_A(A)\\), and then throwing into every object all the other elements that are forced to exist by morphisms of \\(\mathcal{C}\\).
|
|
So intuitively speaking it should be the case that a homomorphism \\(\mathrm{Rep}_A \to G\\) is precisely defined by where that one element \\(a\\) is sent; once we've defined that, *everything* else in our instantiation \\(\mathrm{Rep}_A\\) should be forced by the "preserves morphism structure" property of homomorphisms.
|
|
|
|
This reasoning is made formal in the *Yoneda lemma*:
|
|
|
|
> Pick an arbitrary diagram \\(G : \mathcal{C} \to \mathrm{\mathbf{Set}}\\). Then for every object \\(A : |\mathcal{C}|\\), the homomorphisms from the diagram \\(\mathrm{Rep}_A\\) to \\(G\\) are precisely in correspondence with the elements of \\(G(A)\\). Moreover, this correspondence is natural in both \\(A\\) and \\(G\\).
|
|
|
|
Intuition: the homomorphisms are precisely defined by what happens to the "free generator", and we can get such a homomorphism from any choice of where the "free generator" goes.
|
|
Moreover,
|
|
* this construction is respected by homomorphisms out of \\(G\\) (that's "naturality in \\(G\\)": if we have a homomorphism \\(h : G \to H\\), and we perform the construction on both \\(G\\) and \\(H\\), we find that every homomorphism \\(\mathrm{Rep}_A \xrightarrow{\text{Yoneda corresponding to $x \in GA$}} G \xrightarrow{h} H\\) is equal to \\(\mathrm{Rep}_A \xrightarrow{\text{Yoneda corresponding to $h(x) \in HA$}} H\\));
|
|
* this construction is respected by morphisms \\(A \to B\\) (that's "naturality in \\(A\\)"): this is currently entirely an exercise because I've ground to a halt.
|
|
|
|
The precise construction is like so:
|
|
|
|
* Given an element \\(a \in G(A)\\), define a homomorphism \\(\mathrm{Rep}_A\\) to \\(G\\) by sending \\(f : A \to B\\) to \\((Gf)(a)\\).
|
|
* Given a homomorphism \\(\alpha : \mathrm{Rep}_A\\) to \\(G\\), define an element of \\(G(A)\\) by \\(\alpha(\mathrm{id}_A : A \to A)\\).
|
|
* Show that these are inverse to each other.
|
|
* Prove the naturality conditions.
|
|
|
|
Exercise: do those formally, as follows!
|
|
|
|
1. Prove that the homomorphism \\((f : A \to B) \mapsto (Gf)(a)\\) is indeed a homomorphism (that is, a natural transformation), by writing out the necessary properties which define a natural transformation and showing that they each hold.
|
|
1. Prove (by writing out the equations) that the two Yoneda maps are inverse to each other.
|
|
1. Write out the equations for both naturality conditions (that is, in \\(A\\) and in \\(G\\)) in full, and prove them.
|
|
|
|
# The Yoneda embedding
|
|
|
|
Given any (locally-small) category \\(\mathcal{C}\\) and an object \\(A : |\mathcal{C}|\\), we've seen a way to construct an instantiation of \\(\mathcal{C}\\) in \\(\mathrm{\mathbf{Set}}\\) in a canonical way, representing exactly the structure of \\(\mathcal{C}\\) that was available at \\(A\\).
|
|
|
|
## Definition of "fully faithful"
|
|
|
|
Recall the definitions of "full" and "faithful" for a functor \\(F : \mathcal{C} \to \mathcal{D}\\):
|
|
* The functor is *faithful* if it is injective on parallel arrows: for all \\(A, B : |\mathcal{C}|\\), no two morphisms \\(A \to B\\) get mapped to the same target arrow.
|
|
* The functor is *full* if it is surjective on objects which came from the functor: for all \\(A, B : |\mathcal{C}|\\), and for all \\(g : FA \to FB\\), there is \\(f : A \to B\\) with \\(Ff = g\\).
|
|
|
|
A functor \\(\mathcal{C} \to \mathcal{D}\\) is *fully faithful* if it is both full and faithful.
|
|
While it may collapse away some of \\(\mathcal{C}\\)'s structure, and while it might not hit all of \\(\mathcal{D}\\), it does "locally" preserve all of \\(\mathcal{C}\\)'s structure and introduces no new structure locally: if we fix two objects \\(A, B\\) in \\(\mathcal{C}\\) and restrict ourselves to only looking at \\(A, B\\) and \\(FA, FB\\), the restricted \\(F\\) is a bijection.
|
|
|
|
## The Yoneda embedding is fully faithful
|
|
|
|
Notice that the collection of representable functors (that is, the "sweet spot" instantiations of \\(\mathcal{C}\\)) has got the right number of objects to try and be a copy of \\(\mathcal{C}\\): there's a representable functor for each object of \\(\mathcal{C}\\) already (because that's how we defined the representable functors).
|
|
So what happens if we try and complete this into a copy of \\(\mathcal{C}\\) with all its categorical structure, inside the much larger space of instantiations of \\(\mathcal{C}\\)?
|
|
This would be a nice thing to have, because the space of instantiations of \\(\mathcal{C}\\) is very well-behaved (they're all just sets!).
|
|
|
|
So to view it as a copy of \\(\mathcal{C}\\), we need for any \\(A, B : |\mathcal{C}|\\) and any morphism \\(f : A \to B\\) to find a homomorphism from \\(\mathrm{Rep}_A\\) to \\(\mathrm{Rep}_B\\).
|
|
Take the Yoneda lemma and specialise it by setting \\(G := \mathrm{Rep}_B\\); then we have that the homomorphisms \\(\mathrm{Rep}_A \to \mathrm{Rep}_B\\) are naturally in bijection with the elements of \\(\mathrm{Rep}\_B(A)\\), which is by definition \\(\mathrm{Hom}\_{\mathcal{C}}(B, A)\\).
|
|
|
|
That's… not actually what we wanted!
|
|
It's very close, but the arrows are going the wrong way: we have homomorphisms \\(\mathrm{Rep}\_A \to \mathrm{Rep}\_B\\) corresponding naturally to \\(\mathrm{Hom}\_{\mathcal{C}}(B, A)\\).
|
|
|
|
What we've actually done is built a canonical copy of the *opposite* category of \\(\mathcal{C}\\) inside the space of instantiations of \\(\mathcal{C}\\).
|
|
This canonical copy is called the *Yoneda embedding*, and you can prove that it is full and faithful.
|
|
|
|
That was the *contravariant Yoneda embedding*, which takes \\(\mathcal{C}^{\mathrm{op}}\\) and embeds it fully faithfully in \\(\mathrm{Nat}(\mathcal{C} \to \mathrm{\mathbf{Set}})\\), the space of all \\(\mathrm{\mathbf{Set}}\\)-instantiations of \\(\mathcal{C}\\).
|
|
(That space is more precisely a category, with morphisms being precisely the instantiation homomorphisms, or natural transformations.)
|
|
By flipping all the arrows around, we also get the *covariant Yoneda embedding*, which takes \\(\mathcal{C}\\) and embeds it fully faithfully in \\(\mathrm{Nat}(\mathcal{C}^{\mathrm{op}} \to \mathrm{\mathbf{Set}})\\), the space of all \\(\mathrm{\mathbf{Set}}\\)-instantiations of \\(\mathcal{C}^{\mathrm{op}}\\) (also known as the space of all *presheaves* over \\(\mathcal{C}\\)).
|