Chapter 2.4 - Representable Functors

This commit is contained in:
Igal Tabachnik 2017-09-30 11:32:42 +03:00
parent 09a43d1576
commit ae96156ef5
5 changed files with 55 additions and 81 deletions

Binary file not shown.

View File

@ -1,12 +1,4 @@
\begin{quote} \lettrine[lhang=0.17]{I}{t's about time} we had a little talk about sets. Mathematicians have a
This is part 14 of Categories for Programmers. Previously:
\href{https://bartoszmilewski.com/2015/07/21/free-monoids/}{Free
Monoids}. See the
\href{https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/}{Table
of Contents}.
\end{quote}
It's about time we had a little talk about sets. Mathematicians have a
love/hate relationship with set theory. It's the assembly language of love/hate relationship with set theory. It's the assembly language of
mathematics --- at least it used to be. Category theory tries to step mathematics --- at least it used to be. Category theory tries to step
away from set theory, to some extent. For instance, it's a known fact away from set theory, to some extent. For instance, it's a known fact
@ -58,62 +50,62 @@ Every category comes equipped with a canonical family of mappings to
structure of the category. Let's build one such mapping. structure of the category. Let's build one such mapping.
Let's fix one object \code{a} in \emph{C} and pick another object Let's fix one object \code{a} in \emph{C} and pick another object
\code{x} also in \emph{C}. The hom-set \code{C(a,\ x)} is a set, an \code{x} also in \emph{C}. The hom-set \code{C(a, x)} is a set, an
object in \textbf{Set}. When we vary \code{x}, keeping \code{a} object in \textbf{Set}. When we vary \code{x}, keeping \code{a}
fixed, \code{C(a,\ x)} will also vary in \textbf{Set}. Thus we have a fixed, \code{C(a, x)} will also vary in \textbf{Set}. Thus we have a
mapping from \code{x} to \textbf{Set}.\\ mapping from \code{x} to \textbf{Set}.
\includegraphics[width=3.12500in]{images/hom-set.jpg}
\begin{figure}[H]
\centering
\includegraphics[width=3.12500in]{images/hom-set.jpg}
\end{figure}
\noindent
If we want to stress the fact that we are considering the hom-set as a If we want to stress the fact that we are considering the hom-set as a
mapping in its second argument, we use the notation: mapping in its second argument, we use the notation:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
C(a, -) C(a, -)
\end{Verbatim} \end{Verbatim}
with the dash serving as the placeholder for the argument. with the dash serving as the placeholder for the argument.
This mapping of objects is easily extended to the mapping of morphisms. This mapping of objects is easily extended to the mapping of morphisms.
Let's take a morphism \code{f} in \emph{C} between two arbitrary Let's take a morphism \code{f} in \emph{C} between two arbitrary
objects \code{x} and \code{y}. The object \code{x} is mapped to objects \code{x} and \code{y}. The object \code{x} is mapped to
the set \code{C(a,\ x)}, and the object \code{y} is mapped to the set \code{C(a, x)}, and the object \code{y} is mapped to
\code{C(a,\ y)}, under the mapping we have just defined. If this \code{C(a, y)}, under the mapping we have just defined. If this
mapping is to be a functor, \code{f} must be mapped to a function mapping is to be a functor, \code{f} must be mapped to a function
between the two sets: between the two sets:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
C(a, x) -> C(a, y) C(a, x) -> C(a, y)
\end{Verbatim} \end{Verbatim}
Let's define this function point-wise, that is for each argument Let's define this function point-wise, that is for each argument
separately. For the argument we should pick an arbitrary element of separately. For the argument we should pick an arbitrary element of
\code{C(a,\ x)} --- let's call it \code{h}. Morphisms are \code{C(a, x)} --- let's call it \code{h}. Morphisms are
composable, if they match end to end. It so happens that the target of composable, if they match end to end. It so happens that the target of
\code{h} matches the source of \code{f}, so their composition: \code{h} matches the source of \code{f}, so their composition:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
f ◦ h :: a -> y f ◦ h :: a -> y
\end{Verbatim} \end{Verbatim}
is a morphism going from \code{a} to \code{y}. It is therefore a is a morphism going from \code{a} to \code{y}. It is therefore a
member of \code{C(a,\ y)}. member of \code{C(a, y)}.
\includegraphics[width=3.12500in]{images/hom-functor.jpg} \includegraphics[width=3.12500in]{images/hom-functor.jpg}
We have just found our function from \code{C(a,\ x)} to We have just found our function from \code{C(a, x)} to
\code{C(a,\ y)}, which can serve as the image of \code{f}. If there \code{C(a, y)}, which can serve as the image of \code{f}. If there
is no danger of confusion, we'll write this lifted function as: is no danger of confusion, we'll write this lifted function as:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
C(a, f) C(a, f)
\end{Verbatim} \end{Verbatim}
and its action on a morphism \code{h} as: and its action on a morphism \code{h} as:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
C(a, f) h = f ◦ h C(a, f) h = f ◦ h
\end{Verbatim} \end{Verbatim}
Since this construction works in any category, it must also work in the Since this construction works in any category, it must also work in the
category of Haskell types. In Haskell, the hom-functor is better known category of Haskell types. In Haskell, the hom-functor is better known
as the \code{Reader} functor: as the \code{Reader} functor:
@ -121,11 +113,10 @@ as the \code{Reader} functor:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
type Reader a x = a -> x type Reader a x = a -> x
\end{Verbatim} \end{Verbatim}
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
instance Functor (Reader a) where fmap f h = f . h instance Functor (Reader a) where
fmap f h = f . h
\end{Verbatim} \end{Verbatim}
Now let's consider what happens if, instead of fixing the source of the Now let's consider what happens if, instead of fixing the source of the
hom-set, we fix the target. In other words, we're asking the question if hom-set, we fix the target. In other words, we're asking the question if
the mapping the mapping
@ -133,11 +124,10 @@ the mapping
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
C(-, a) C(-, a)
\end{Verbatim} \end{Verbatim}
is also a functor. It is, but instead of being covariant, it's is also a functor. It is, but instead of being covariant, it's
contravariant. That's because the same kind of matching of morphisms end contravariant. That's because the same kind of matching of morphisms end
to end results in postcomposition by \code{f}; rather than to end results in postcomposition by \code{f}; rather than
precomposition, as was the case with \code{C(a,\ -)}. precomposition, as was the case with \code{C(a, -)}.
We have already seen this contravariant functor in Haskell. We called it We have already seen this contravariant functor in Haskell. We called it
\code{Op}: \code{Op}:
@ -145,21 +135,22 @@ We have already seen this contravariant functor in Haskell. We called it
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
type Op a x = x -> a type Op a x = x -> a
\end{Verbatim} \end{Verbatim}
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
instance Contravariant (Op a) where contramap f h = h . f instance Contravariant (Op a) where
contramap f h = h . f
\end{Verbatim} \end{Verbatim}
Finally, if we let both objects vary, we get a profunctor Finally, if we let both objects vary, we get a profunctor
\code{C(-,\ =)}, which is contravariant in the first argument and \code{C(-, =)}, which is contravariant in the first argument and
covariant in the second (to underline the fact that the two arguments covariant in the second (to underline the fact that the two arguments
may vary independently, we use a double dash as the second placeholder). may vary independently, we use a double dash as the second placeholder).
We have seen this profunctor before, when we talked about functoriality: We have seen this profunctor before, when we talked about functoriality:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
instance Profunctor (->) where dimap ab cd bc = cd . bc . ab lmap = flip (.) rmap = (.) instance Profunctor (->) where
dimap ab cd bc = cd . bc . ab
lmap = flip (.)
rmap = (.)
\end{Verbatim} \end{Verbatim}
The important lesson is that this observation holds in any category: the The important lesson is that this observation holds in any category: the
mapping of objects to hom-sets is functorial. Since contravariance is mapping of objects to hom-sets is functorial. Since contravariance is
equivalent to a mapping from the opposite category, we can state this equivalent to a mapping from the opposite category, we can state this
@ -177,11 +168,11 @@ structure-preserving mapping to \textbf{Set} is often called a
\newterm{representation}. We are representing objects and morphisms of \newterm{representation}. We are representing objects and morphisms of
\emph{C} as sets and functions in \textbf{Set}. \emph{C} as sets and functions in \textbf{Set}.
The functor \code{C(a,\ -)} itself is sometimes called representable. The functor \code{C(a, -)} itself is sometimes called representable.
More generally, any functor \code{F} that is naturally isomorphic to More generally, any functor \code{F} that is naturally isomorphic to
the hom-functor, for some choice of \code{a}, is called the hom-functor, for some choice of \code{a}, is called
\newterm{representable}. Such functor must necessarily be \newterm{representable}. Such functor must necessarily be
\textbf{Set}-valued, since \code{C(a,\ -)} is. \textbf{Set}-valued, since \code{C(a, -)} is.
I said before that we often think of isomorphic sets as identical. More I said before that we often think of isomorphic sets as identical. More
generally, we think of isomorphic \newterm{objects} in a category as generally, we think of isomorphic \newterm{objects} in a category as
@ -207,7 +198,7 @@ them.
Let's analyze the definition of the representable functor from this Let's analyze the definition of the representable functor from this
perspective. For \code{F} to be representable we require that: There perspective. For \code{F} to be representable we require that: There
be an object \code{a} in \emph{C}; one natural transformation α from be an object \code{a} in \emph{C}; one natural transformation α from
\code{C(a,\ -)} to \code{F}; another natural transformation, β, in \code{C(a, -)} to \code{F}; another natural transformation, β, in
the opposite direction; and that their composition be the identity the opposite direction; and that their composition be the identity
natural transformation. natural transformation.
@ -215,55 +206,48 @@ Let's look at the component of α at some object \code{x}. It's a
function in \textbf{Set}: function in \textbf{Set}:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
αx :: C(a, x) -> F x α\textsubscript{x} :: C(a, x) -> F x
\end{Verbatim} \end{Verbatim}
The naturality condition for this transformation tells us that, for any The naturality condition for this transformation tells us that, for any
morphism \code{f} from \code{x} to \code{y}, the following diagram morphism \code{f} from \code{x} to \code{y}, the following diagram
commutes: commutes:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
F f ◦ αx = αy ◦ C(a, f) F f ◦ α\textsubscript{x} = α\textsubscript{y} ◦ C(a, f)
\end{Verbatim} \end{Verbatim}
In Haskell, we would replace natural transformations with polymorphic In Haskell, we would replace natural transformations with polymorphic
functions: functions:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
alpha :: forall x. (a -> x) -> F x alpha :: forall x. (a -> x) -> F x
\end{Verbatim} \end{Verbatim}
with the optional \code{forall} quantifier. The naturality condition with the optional \code{forall} quantifier. The naturality condition
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
fmap f . alpha = alpha . fmap f fmap f . alpha = alpha . fmap f
\end{Verbatim} \end{Verbatim}
is automatically satisfied due to parametricity (it's one of those is automatically satisfied due to parametricity (it's one of those
theorems for free I mentioned earlier), with the understanding that theorems for free I mentioned earlier), with the understanding that
\code{fmap} on the left is defined by the functor \code{F}, whereas \code{fmap} on the left is defined by the functor \code{F}, whereas
the one on the right is defined by the reader functor. Since the one on the right is defined by the reader functor. Since
\code{fmap} for reader is just function precomposition, we can be even \code{fmap} for reader is just function precomposition, we can be even
more explicit. Acting on \code{h}, an element of \code{C(a,\ x)}, more explicit. Acting on \code{h}, an element of \code{C(a, x)},
the naturality condition simplifies to: the naturality condition simplifies to:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
fmap f (alpha h) = alpha (f . h) fmap f (alpha h) = alpha (f . h)
\end{Verbatim} \end{Verbatim}
The other transformation, \code{beta}, goes the opposite way: The other transformation, \code{beta}, goes the opposite way:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
beta :: forall x. F x -> (a -> x) beta :: forall x. F x -> (a -> x)
\end{Verbatim} \end{Verbatim}
It must respect naturality conditions, and it must be the inverse of α: It must respect naturality conditions, and it must be the inverse of α:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
α ◦ β = id = β ◦ α α ◦ β = id = β ◦ α
\end{Verbatim} \end{Verbatim}
We will see later that a natural transformation from \code{C(a, -)}
We will see later that a natural transformation from \code{C(a,\ -)}
to any \textbf{Set}-valued functor always exists (Yoneda's lemma) but it to any \textbf{Set}-valued functor always exists (Yoneda's lemma) but it
is not necessarily invertible. is not necessarily invertible.
@ -274,7 +258,6 @@ the job:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
alpha :: forall x. (Int -> x) -> [x] alpha h = map h [12] alpha :: forall x. (Int -> x) -> [x] alpha h = map h [12]
\end{Verbatim} \end{Verbatim}
I have arbitrarily picked the number 12 and created a singleton list I have arbitrarily picked the number 12 and created a singleton list
with it. I can then \code{fmap} the function \code{h} over this list with it. I can then \code{fmap} the function \code{h} over this list
and get a list of the type returned by \code{h}. (There are actually and get a list of the type returned by \code{h}. (There are actually
@ -286,7 +269,6 @@ The naturality condition is equivalent to the composability of
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
map f (map h [12]) = map (f . h) [12] map f (map h [12]) = map (f . h) [12]
\end{Verbatim} \end{Verbatim}
But if we tried to find the inverse transformation, we would have to go But if we tried to find the inverse transformation, we would have to go
from a list of arbitrary type \code{x} to a function returning from a list of arbitrary type \code{x} to a function returning
\code{x}: \code{x}:
@ -294,7 +276,6 @@ from a list of arbitrary type \code{x} to a function returning
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
beta :: forall x. [x] -> (Int -> x) beta :: forall x. [x] -> (Int -> x)
\end{Verbatim} \end{Verbatim}
You might think of retrieving an \code{x} from the list, e.g., using You might think of retrieving an \code{x} from the list, e.g., using
\code{head}, but that won't work for an empty list. Notice that there \code{head}, but that won't work for an empty list. Notice that there
is no choice for the type \code{a} (in place of \code{Int}) that is no choice for the type \code{a} (in place of \code{Int}) that
@ -304,19 +285,21 @@ Remember when we talked about Haskell (endo-) functors being a little
like containers? In the same vein we can think of representable functors like containers? In the same vein we can think of representable functors
as containers for storing memoized results of function calls (the as containers for storing memoized results of function calls (the
members of hom-sets in Haskell are just functions). The representing members of hom-sets in Haskell are just functions). The representing
object, the type \code{a} in \code{C(a,\ -)}, is thought of as the object, the type \code{a} in \code{C(a, -)}, is thought of as the
key type, with which we can access the tabulated values of a function. key type, with which we can access the tabulated values of a function.
The transformation we called α is called \code{tabulate}, and its The transformation we called α is called \code{tabulate}, and its
inverse, β, is called \code{index}. Here's a (slightly simplified) inverse, β, is called \code{index}. Here's a (slightly simplified)
\code{Representable} class definition: \code{Representable} class definition:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
class Representable f where type Rep f :: * tabulate :: (Rep f -> x) -> f x index :: f x -> Rep f -> x class Representable f where
type Rep f :: *
tabulate :: (Rep f -> x) -> f x
index :: f x -> Rep f -> x
\end{Verbatim} \end{Verbatim}
Notice that the representing type, our \code{a}, which is called Notice that the representing type, our \code{a}, which is called
\code{Rep\ f} here, is part of the definition of \code{Rep f} here, is part of the definition of
\code{Representable}. The star just means that \code{Rep\ f} is a \code{Representable}. The star just means that \code{Rep f} is a
type (as opposed to a type constructor, or other more exotic kinds). type (as opposed to a type constructor, or other more exotic kinds).
Infinite lists, or streams, which cannot be empty, are representable. Infinite lists, or streams, which cannot be empty, are representable.
@ -324,7 +307,6 @@ Infinite lists, or streams, which cannot be empty, are representable.
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
data Stream x = Cons x (Stream x) data Stream x = Cons x (Stream x)
\end{Verbatim} \end{Verbatim}
You can think of them as memoized values of a function taking an You can think of them as memoized values of a function taking an
\code{Integer} as an argument. (Strictly speaking, I should be using \code{Integer} as an argument. (Strictly speaking, I should be using
non-negative natural numbers, but I didn't want to complicate the code.) non-negative natural numbers, but I didn't want to complicate the code.)
@ -335,33 +317,33 @@ values are evaluated on demand. You access the memoized values using
\code{index}: \code{index}:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
instance Representable Stream where type Rep Stream = Integer tabulate f = Cons (f 0) (tabulate (f . (+1))) index (Cons b bs) n = if n == 0 then b else index bs (n - 1) instance Representable Stream where
type Rep Stream = Integer
tabulate f = Cons (f 0) (tabulate (f . (+1)))
index (Cons b bs) n = if n == 0 then b else index bs (n - 1)
\end{Verbatim} \end{Verbatim}
It's interesting that you can implement a single memoization scheme to It's interesting that you can implement a single memoization scheme to
cover a whole family of functions with arbitrary return types. cover a whole family of functions with arbitrary return types.
Representability for contravariant functors is similarly defined, except Representability for contravariant functors is similarly defined, except
that we keep the second argument of \code{C(-,\ a)} fixed. Or, that we keep the second argument of \code{C(-, a)} fixed. Or,
equivalently, we may consider functors from \emph{C}\textsuperscript{op} equivalently, we may consider functors from \emph{C}\textsuperscript{op}
to \textbf{Set}, because \code{Cop(a,\ -)} is the same as to \textbf{Set}, because \code{C\textsuperscript{op}(a, -)} is the same as
\code{C(-,\ a)}. \code{C(-, a)}.
There is an interesting twist to representability. Remember that There is an interesting twist to representability. Remember that
hom-sets can internally be treated as exponential objects, in cartesian hom-sets can internally be treated as exponential objects, in cartesian
closed categories. The hom-set \code{C(a,\ x)} is equivalent to closed categories. The hom-set \code{C(a, x)} is equivalent to
\code{xa}, and for a representable functor \code{F} we can write: \code{xa}, and for a representable functor \code{F} we can write:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
-a = F -a = F
\end{Verbatim} \end{Verbatim}
Let's take the logarithm of both sides, just for kicks: Let's take the logarithm of both sides, just for kicks:
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
a = log F a = log F
\end{Verbatim} \end{Verbatim}
Of course, this is a purely formal transformation, but if you know some Of course, this is a purely formal transformation, but if you know some
of the properties of logarithms, it is quite helpful. In particular, it of the properties of logarithms, it is quite helpful. In particular, it
turns out that functors that are based on product types can be turns out that functors that are based on product types can be
@ -385,6 +367,7 @@ explore alternative implementations that have practical value.
\section{Challenges}\label{challenges} \section{Challenges}\label{challenges}
\begin{enumerate} \begin{enumerate}
\tightlist
\item \item
Show that the hom-functors map identity morphisms in \emph{C} to Show that the hom-functors map identity morphisms in \emph{C} to
corresponding identity functions in \textbf{Set}. corresponding identity functions in \textbf{Set}.
@ -404,7 +387,6 @@ explore alternative implementations that have practical value.
\begin{Verbatim}[commandchars=\\\{\}] \begin{Verbatim}[commandchars=\\\{\}]
Pair a = Pair a a Pair a = Pair a a
\end{Verbatim} \end{Verbatim}
is representable. Can you guess the type that represents it? Implement is representable. Can you guess the type that represents it? Implement
\code{tabulate} and \code{index}. \code{tabulate} and \code{index}.
\end{enumerate} \end{enumerate}
@ -417,15 +399,4 @@ Pair a = Pair a a
The Catsters video about The Catsters video about
\href{https://www.youtube.com/watch?v=4QgjKUzyrhM}{representable \href{https://www.youtube.com/watch?v=4QgjKUzyrhM}{representable
functors}. functors}.
\end{enumerate} \end{enumerate}
Next:
\href{https://bartoszmilewski.com/2015/09/01/the-yoneda-lemma/}{The
Yoneda Lemma}.
\section{Acknowledgments}\label{acknowledgments}
I'd like to thank Gershom Bazerman for checking my math and logic, and
André van Meulebrouck, who has been volunteering his editing help
throughout this series of posts.\\
\href{https://twitter.com/BartoszMilewski}{Follow @BartoszMilewski}

View File

@ -22,7 +22,7 @@ categories in
Transformations}). Let's use the notation \code{{[}C, Set{]}} for the Transformations}). Let's use the notation \code{{[}C, Set{]}} for the
functor category from \emph{C} to \textbf{Set}. You may also recall that functor category from \emph{C} to \textbf{Set}. You may also recall that
hom-functors are the prototypical hom-functors are the prototypical
\hyperref[representable-functors]{representable \hyperref[chap-representable-functors]{representable
functors}. functors}.
Every time we have a mapping of objects between two categories, it's Every time we have a mapping of objects between two categories, it's

View File

@ -402,7 +402,7 @@ description of the adjunction to Haskell code. I highly encourage this
as an exercise. as an exercise.
We are now ready to explain why, in Haskell, the right adjoint is We are now ready to explain why, in Haskell, the right adjoint is
automatically a \hyperref[representable-functors]{representable automatically a \hyperref[chap-representable-functors]{representable
functor}. The reason for this is that, to the first approximation, we functor}. The reason for this is that, to the first approximation, we
can treat the category of Haskell types as the category of sets. can treat the category of Haskell types as the category of sets.

View File

@ -118,6 +118,9 @@ PDF compiled by @url{https://github.com/hmemcpy/milewski-ctfp-pdf, Igal Tabachni
\chapter{Limits and Colimits}\label{limits-and-colimits} \chapter{Limits and Colimits}\label{limits-and-colimits}
\subfile{content/2.2/Limits and Colimits} \subfile{content/2.2/Limits and Colimits}
\chapter{Representable Functors}\label{chap-representable-functors}
\subfile{content/2.4/Representable Functors}
\chapter{The Yoneda Lemma}\label{the-yoneda-lemma} \chapter{The Yoneda Lemma}\label{the-yoneda-lemma}
\subfile{content/2.5/The Yoneda Lemma} \subfile{content/2.5/The Yoneda Lemma}