% !TEX root = ../../ctfp-print.tex

\lettrine[lhang=0.17]{I}{t seems like in category theory} everything is related to everything and
everything can be viewed from many angles. Take for instance the
universal construction of the \hyperref[products-and-coproducts]{product}.
Now that we know more about \hyperref[functors]{functors} and
\hyperref[natural-transformations]{natural transformations}, can we simplify and, possibly, generalize it? Let us
try.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.3\textwidth]{images/productpattern.jpg}
\end{figure}

\noindent
The construction of a product starts with the selection of two objects
$a$ and $b$, whose product we want to construct. But what
does it mean to \emph{select objects}? Can we rephrase this action in
more categorical terms? Two objects form a pattern --- a very simple
pattern. We can abstract this pattern into a category --- a very simple
category, but a category nevertheless. It's a category that we'll call
$\cat{2}$. It contains just two objects, $1$ and $2$, and no morphisms
other than the two obligatory identities. Now we can rephrase the
selection of two objects in $\cat{C}$ as the act of defining a functor $D$
from the category $\cat{2}$ to $\cat{C}$. A functor maps objects to
objects, so its image is just two objects (or it could be one, if the
functor collapses objects, which is fine too). It also maps morphisms
--- in this case it simply maps identity morphisms to identity
morphisms.

What's great about this approach is that it builds on categorical
notions, eschewing the imprecise descriptions like ``selecting
objects,'' taken straight from the hunter-gatherer lexicon of our
ancestors. And, incidentally, it is also easily generalized, because
nothing can stop us from using categories more complex than $\cat{2}$
to define our patterns.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/two.jpg}
\end{figure}

\noindent
But let's continue. The next step in the definition of a product is the
selection of the candidate object $c$. Here again, we could
rephrase the selection in terms of a functor from a singleton category.
And indeed, if we were using Kan extensions, that would be the right
thing to do. But since we are not ready for Kan extensions yet, there is
another trick we can use: a constant functor $\Delta$ from the same category
$\cat{2}$ to $\cat{C}$. The selection of $c$ in $\cat{C}$ can be
done with $\Delta_c$. Remember, $\Delta_c$ maps all
objects into $c$ and all morphisms into $\idarrow[c]$.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/twodelta.jpg}
\end{figure}

\noindent
Now we have two functors, $\Delta_c$ and $D$ going between
$\cat{2}$ and $\cat{C}$ so it's only natural to ask about natural
transformations between them. Since there are only two objects in
$\cat{2}$, a natural transformation will have two components. Object $1$
in $\cat{2}$ is mapped to $c$ by $\Delta_c$ and to
$a$ by $D$. So the component of a natural transformation between
$\Delta_c$ and $D$ at $1$ is a morphism from $c$ to
$a$. We can call it $p$. Similarly, the second component
is a morphism $q$ from $c$ to $b$ --- the image of
the object $2$ in $\cat{2}$ under $D$. But these are exactly like the two
projections we used in our original definition of the product. So
instead of talking about selecting objects and projections, we can just
talk about picking functors and natural transformations. It so happens
that in this simple case the naturality condition for our transformation
is trivially satisfied, because there are no morphisms (other than the
identities) in $\cat{2}$.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/productcone.jpg}
\end{figure}

\noindent
A generalization of this construction to categories other than
$\cat{2}$ --- ones that, for instance, contain non-trivial morphisms
--- will impose naturality conditions on the transformation between
$\Delta_c$ and $D$. We call such a transformation a \emph{cone},
because the image of $\Delta$ is the apex of a cone/pyramid whose sides are
formed by the components of the natural transformation. The image of $D$
forms the base of the cone.

In general, to build a cone, we start with a category $\cat{I}$ that
defines the pattern. It's a small, often finite category. We pick a
functor $D$ from $\cat{I}$ to $\cat{C}$ and call it (or its image) a
\emph{diagram}. We pick some $c$ in $\cat{C}$ as the apex of our
cone. We use it to define the constant functor $\Delta_c$ from
$\cat{I}$ to $\cat{C}$. A natural transformation from $\Delta_c$
to $D$ is then our cone. For a finite $\cat{I}$ it's just a bunch of
morphisms connecting $c$ to the diagram: the image of $\cat{I}$
under $D$.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/cone.jpg}
\end{figure}

\noindent
Naturality requires that all triangles (the walls of the pyramid) in
this diagram commute. Indeed, take any morphism $f$ in $\cat{I}$.
The functor $D$ maps it to a morphism $D f$ in $\cat{C}$, a
morphism that forms the base of some triangle. The constant functor
$\Delta_c$ maps $f$ to the identity morphism on
$c$. $\Delta$ squishes the two ends of the morphism into one object, and
the naturality square becomes a commuting triangle. The two arms of this
triangle are the components of the natural transformation.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/conenaturality.jpg}
\end{figure}

\noindent
So that's one cone. What we are interested in is the \newterm{universal
  cone} --- just like we picked a universal object for our definition of a
product.

There are many ways to go about it. For instance, we may define a
\emph{category of cones} based on a given functor $D$. Objects in that
category are cones. Not every object $c$ in $\cat{C}$ can be an
apex of a cone, though, because there may be no natural transformation
between $\Delta_c$ and $D$.

To make it a category, we also have to define morphisms between cones.
These would be fully determined by morphisms between their apexes. But
not just any morphism will do. Remember that, in our construction of the
product, we imposed the condition that the morphisms between candidate
objects (the apexes) must be common factors for the projections. For
instance:

\src{snippet01}

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/productranking.jpg}
\end{figure}

This condition translates, in the general case, to the condition that
the triangles whose one side is the factorizing morphism all commute.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/conecommutativity.jpg}
  \caption{The commuting triangle connecting two cones, with the factorizing
    morphism $h$ (here, the lower cone is the universal one, with
    $\Lim[D]$ as its apex)}
\end{figure}

\noindent
We'll take those factorizing morphisms as the morphisms in our category
of cones. It's easy to check that those morphisms indeed compose, and
that the identity morphism is a factorizing morphism as well. Cones
therefore form a category.

Now we can define the universal cone as the \emph{terminal object} in
the category of cones. The definition of the terminal object states that
there is a unique morphism from any other object to that object. In our
case it means that there is a unique factorizing morphism from the apex
of any other cone to the apex of the universal cone. We call this
universal cone the \emph{limit} of the diagram $D$, $\Lim[D]$ (in
the literature, you'll often see a left arrow pointing towards $I$
under the $\Lim$ sign). Often, as a shorthand, we call the apex of
this cone the limit (or the limit object).

The intuition is that the limit embodies the properties of the whole
diagram in a single object. For instance, the limit of our two-object
diagram is the product of two objects. The product (together with the
two projections) contains the information about both objects. And being
universal means that it has no extraneous junk.

\section{Limit as a Natural Isomorphism}

There is still something unsatisfying about this definition of a limit.
I mean, it's workable, but we still have this commutativity condition
for the triangles that are linking any two cones. It would be so much
more elegant if we could replace it with some naturality condition. But
how?

We are no longer dealing with one cone but with a whole collection (in
fact, a category) of cones. If the limit exists (and --- let's make it
clear --- there's no guarantee of that), one of those cones is the
universal cone. For every other cone we have a unique factorizing
morphism that maps its apex, let's call it $c$, to the apex of
the universal cone, which we named $\Lim[D]$. (In fact, I can skip
the word ``other'', because the identity morphism maps the universal
cone to itself and it trivially factorizes through itself.) Let me
repeat the important part: given any cone, there is a unique morphism of
a special kind. We have a mapping of cones to special morphisms, and
it's a one-to-one mapping.

This special morphism is a member of the hom-set $\cat{C}(c, \Lim[D])$.
The other members of this hom-set are less fortunate, in the sense that
they don't factorize the mapping of the two cones. What we want is to be able to
pick, for each $c$, one morphism from the set
$\cat{C}(c, \Lim[D])$ --- a morphism that satisfies the particular
commutativity condition. Does that sound like defining a natural
transformation? It most certainly does!

But what are the functors that are related by this transformation?

One functor is the mapping of $c$ to the set
$\cat{C}(c, \Lim[D])$. It's a functor from $\cat{C}$ to $\Set$ ---
it maps objects to sets. In fact it's a contravariant functor. Here's
how we define its action on morphisms: Let's take a morphism $f$
from $c'$ to $c$:
\[f \Colon c' \to c\]
Our functor maps $c'$ to the set
$\cat{C}(c', \Lim[D])$. To define the action of this functor on
$f$ (in other words, to lift $f$), we have to define the
corresponding mapping between $\cat{C}(c, \Lim[D])$ and
$\cat{C}(c', \Lim[D])$. So let's pick one element $u$ of
$\cat{C}(c, \Lim[D])$ and see if we can map it to some element of
$\cat{C}(c', \Lim[D])$. An element of a hom-set is a morphism, so
we have:
\[u \Colon c \to \Lim[D]\]
We can precompose $u$ with $f$ to get:
\[u \circ f \Colon c' \to \Lim[D]\]
And that's an element of $\cat{C}(c', \Lim[D])$--- so indeed, we
have found a mapping of morphisms:

\src{snippet02}
Notice the inversion in the order of $c$ and $c'$
characteristic of a \emph{contravariant} functor.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/homsetmapping.jpg}
\end{figure}

\noindent
To define a natural transformation, we need another functor that's also
a mapping from $\cat{C}$ to $\Set$. But this time we'll consider a
set of cones. Cones are just natural transformations, so we are looking
at the set of natural transformations $\mathit{Nat}(\Delta_c, D)$. The mapping
from $c$ to this particular set of natural transformations is a
(contravariant) functor. How can we show that? Again, let's define its
action on a morphism:
\[f \Colon c' \to c\]
The lifting of $f$ should be a mapping of natural transformations
between two functors that go from $\cat{I}$ to $\cat{C}$:
\[\mathit{Nat}(\Delta_c, D) \to \mathit{Nat}(\Delta_{c'}, D)\]
How do we map natural transformations? Every natural transformation is a
selection of morphisms --- its components --- one morphism per element
of $\cat{I}$. A component of some $\alpha$ (a member of $\mathit{Nat}(\Delta_c, D)$) at
$a$ (an object in $\cat{I}$) is a morphism:
\[\alpha_a \Colon \Delta_c a \to D a\]
or, using the definition of the constant functor $\Delta$,
\[\alpha_a \Colon c \to D a\]
Given $f$ and $\alpha$, we have to construct a $\beta$, a member of
$\mathit{Nat}(\Delta_{c'}, D)$. Its component at $a$ should be a
morphism:
\[\beta_a \Colon c' \to D a\]
We can easily get the latter ($\beta_a$) from the former ($\alpha_a$) by precomposing it with
$f$:
\[\beta_a = \alpha_a \circ f\]
It's relatively easy to show that those components indeed add up to a
natural transformation.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.4\textwidth]{images/natmapping.jpg}
\end{figure}

\noindent
Given our morphism $f$, we have thus built a mapping between two
natural transformations, component-wise. This mapping defines
\code{contramap} for the functor:
\[c \to \mathit{Nat}(\Delta_c, D)\]
What I have just done is to show you that we have two (contravariant)
functors from $\cat{C}$ to $\Set$. I haven't made any assumptions
--- these functors always exist.

Incidentally, the first of these functors plays an important role in
category theory, and we'll see it again when we talk about Yoneda's
lemma. There is a name for contravariant functors from any category
$\cat{C}$ to $\Set$: they are called ``presheaves''. This one is
called a \newterm{representable presheaf}. The second functor is also a
presheaf.

Now that we have two functors, we can talk about natural transformations
between them. So without further ado, here's the conclusion: A functor
$D$ from $\cat{I}$ to $\cat{C}$ has a limit $\Lim[D]$ if and
only if there is a natural isomorphism between the two functors I have
just defined:
\[\cat{C}(c, \Lim[D]) \simeq \mathit{Nat}(\Delta_c, D)\]
Let me remind you what a natural isomorphism is. It's a natural
transformation whose every component is an isomorphism, that is to say
an invertible morphism.

I'm not going to go through the proof of this statement. The procedure
is pretty straightforward if not tedious. When dealing with natural
transformations, you usually focus on components, which are morphisms.
In this case, since the target of both functors is $\Set$, the
components of the natural isomorphism will be functions. These are
higher order functions, because they go from the hom-set to the set of
natural transformations. Again, you can analyze a function by
considering what it does to its argument: here the argument will be a
morphism --- a member of $\cat{C}(c, \Lim[D])$ --- and the result will
be a natural transformation --- a member of $\mathit{Nat}(\Delta_c, D)$, or
what we have called a cone. This natural transformation, in turn, has
its own components, which are morphisms. So it's morphisms all the way
down, and if you can keep track of them, you can prove the statement.

The most important result is that the naturality condition for this
isomorphism is exactly the commutativity condition for the mapping of
cones.

As a preview of coming attractions, let me mention that the set
$\mathit{Nat}(\Delta_c, D)$ can be thought of as a hom-set in the functor
category; so our natural isomorphism relates two hom-sets, which points
at an even more general relationship called an adjunction.

\section{Examples of Limits}

We've seen that the categorical product is a limit of a diagram
generated by a simple category we called $\cat{2}$.

There is an even simpler example of a limit: the terminal object. The
first impulse would be to think of a singleton category as leading to a
terminal object, but the truth is even starker than that: the terminal
object is a limit generated by an empty category. A functor from an
empty category selects no object, so a cone shrinks to just the apex.
The universal cone is the lone apex that has a unique morphism coming to
it from any other apex. You will recognize this as the definition of the
terminal object.

The next interesting limit is called the \emph{equalizer}. It's a limit
generated by a two-element category with two parallel morphisms going
between them (and, as always, the identity morphisms). This category
selects a diagram in $\cat{C}$ consisting of two objects, $a$ and
$b$, and two morphisms:

\src{snippet03}

To build a cone over this diagram, we have to add the apex, $c$
and two projections:

\src{snippet04}

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/equalizercone.jpg}
\end{figure}

\noindent
We have two triangles that must commute:

\src{snippet05}

This tells us that $q$ is uniquely determined by one of these
equations, say, \code{q = f . p}, and we can omit it from the
picture. So we are left with just one condition:

\src{snippet06}

The way to think about it is that, if we restrict our attention to
$\Set$, the image of the function $p$ selects a subset of
$a$. When restricted to this subset, the functions $f$ and
$g$ are equal.

For instance, take $a$ to be the two-dimensional plane
parameterized by coordinates $x$ and $y$. Take $b$
to be the real line, and take:

\src{snippet07}

The equalizer for these two functions is the set of real numbers (the
apex, $c$) and the function:

\src{snippet08}

Notice that $(p~t)$ defines a straight line in the
two-dimensional plane. Along this line, the two functions are equal.

Of course, there are other sets $c'$ and functions
$p'$ that may lead to the equality:

\src{snippet09}

but they all uniquely factor out through $p$. For instance, we
can take the singleton set $\cat{()}$ as $c'$ and the
function:

\src{snippet10}

It's a good cone, because $f (0, 0) = g (0, 0)$. But it's
not universal, because of the unique factorization through $h$:

\src{snippet11}

with

\src{snippet12}

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/equilizerlimit.jpg}
\end{figure}

\noindent
An equalizer can thus be used to solve equations of the type
$f~x = g~x$. But it's much more general, because it's defined
in terms of objects and morphisms rather than algebraically.

An even more general idea of solving an equation is embodied in another
limit --- the pullback. Here, we still have two morphisms that we want
to equate, but this time their domains are different. We start with a
three-object category of the shape:
$1\rightarrow2\leftarrow3$. The diagram corresponding to
this category consists of three objects, $a$, $b$, and
$c$, and two morphisms:

\src{snippet13}

This diagram is often called a \emph{cospan}.

A cone built on top of this diagram consists of the apex, $d$,
and three morphisms:

\src{snippet14}

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/pullbackcone.jpg}
\end{figure}

\noindent
Commutativity conditions tell us that $r$ is completely
determined by the other morphisms, and can be omitted from the picture.
So we are only left with the following condition:

\src{snippet15}
A pullback is a universal cone of this shape.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/pullbacklimit.jpg}
\end{figure}

\noindent
Again, if you narrow your focus down to sets, you can think of the
object $d$ as consisting of pairs of elements from $a$ and
$c$ for which $f$ acting on the first component is equal
to $g$ acting on the second component. If this is still too
general, consider the special case in which $g$ is a constant
function, say $g~\_ = 1.23$ (assuming that $b$ is a set
of real numbers). Then you are really solving the equation:

\src{snippet16}

In this case, the choice of $c$ is irrelevant (as long as it's
not an empty set), so we can take it to be a singleton set. The set
$a$ could, for instance, be the set of three-dimensional vectors,
and $f$ the vector length. Then the pullback is the set of pairs
$(v, ())$, where $v$ is a vector of length 1.23 (a
solution to the equation $\sqrt{(x^{2}+y^{2}+z^{2})} = 1.23$), and
$()$ is the dummy element of the singleton set.

But pullbacks have more general applications, also in programming. For
instance, consider C++ classes as a category in which morphism are
arrows that connect subclasses to superclasses. We'll consider
inheritance a transitive property, so if \code{C} inherits from \code{B} and \code{B}
inherits from \code{A} then we'll say that \code{C} inherits from \code{A} (after all, you
can pass a pointer to \code{C} where a pointer to \code{A} is expected). Also, we'll
assume that \code{C} inherits from \code{C}, so we have the identity arrow for every
class. This way subclassing is aligned with subtyping. C++ also supports
multiple inheritance, so you can construct a diamond inheritance diagram
with two classes \code{B} and \code{C} inheriting from \code{A}, and a fourth class \code{D}
multiply inheriting from \code{B} and \code{C}. Normally, \code{D} would get two copies of \code{A},
which is rarely desirable; but you can use virtual inheritance to have
just one copy of \code{A} in \code{D}.

What would it mean to have \code{D} be a pullback in this diagram? It would
mean that any class \code{E} that multiply inherits from \code{B} and \code{C} is also a
subclass of \code{D}. This is not directly expressible in C++, where subtyping
is nominal (the C++ compiler wouldn't infer this kind of class
relationship --- it would require ``duck typing''). But we could go
outside of the subtyping relationship and instead ask whether a cast
from \code{E} to \code{D} would be safe or not. This cast would be safe if \code{D} were the
bare-bone combination of \code{B} and \code{C}, with no additional data and no
overriding of methods. And, of course, there would be no pullback if
there is a name conflict between some methods of \code{B} and \code{C}.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.25\textwidth]{images/classes.jpg}
\end{figure}

\noindent
There's also a more advanced use of a pullback in type inference. There
is often a need to \emph{unify} types of two expressions. For instance,
suppose that the compiler wants to infer the type of a function:

\begin{snip}{haskell}
twice f x = f (f x)
\end{snip}
It will assign preliminary types to all variables and sub-expressions.
In particular, it will assign:

\begin{snip}{haskell}
f       :: t0
x       :: t1
f x     :: t2
f (f x) :: t3
\end{snip}
from which it will deduce that:

\begin{snip}{haskell}
twice :: t0 -> t1 -> t3
\end{snip}
It will also come up with a set of constraints resulting from the rules
of function application:

\begin{snip}{haskell}
t0 = t1 -> t2 -- because f is applied to x
t0 = t2 -> t3 -- because f is applied to (f x)
\end{snip}
These constraints have to be unified by finding a set of types (or type
variables) that, when substituted for the unknown types in both
expressions, produce the same type. One such substitution is:

\begin{snip}{haskell}
t1 = t2 = t3 = Int
twice :: (Int -> Int) -> Int -> Int
\end{snip}
but, obviously, it's not the most general one. The most general
substitution is obtained using a pullback. I won't go into the details,
because they are beyond the scope of this book, but you can convince
yourself that the result should be:

\begin{snip}{haskell}
twice :: (t -> t) -> t -> t
\end{snip}
with \code{t} a free type variable.

\section{Colimits}

Just like all constructions in category theory, limits have their dual
image in opposite categories. When you invert the direction of all
arrows in a cone, you get a co-cone, and the universal one of those is
called a colimit. Notice that the inversion also affects the factorizing
morphism, which now flows from the universal co-cone to any other
co-cone.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/colimit.jpg}
  \caption{Cocone with a factorizing morphism $h$ connecting two apexes.}
\end{figure}

\noindent
A typical example of a colimit is a coproduct, which corresponds to the
diagram generated by $\cat{2}$, the category we've used in the
definition of the product.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.35\textwidth]{images/coproductranking.jpg}
\end{figure}

\noindent
Both the product and the coproduct embody the essence of a pair of
objects, each in a different way.

Just like the terminal object was a limit, so the initial object is a
colimit corresponding to the diagram based on an empty category.

The dual of the pullback is called the \emph{pushout}. It's based on a
diagram called a span, generated by the category
$1\leftarrow2\rightarrow3$.

\section{Continuity}

I said previously that functors come close to the idea of continuous
mappings of categories, in the sense that they never break existing
connections (morphisms). The actual definition of a \emph{continuous
  functor} $F$ from a category $\cat{C}$ to $\cat{C'}$ includes the
requirement that the functor preserve limits. Every diagram $D$
in $\cat{C}$ can be mapped to a diagram $F \circ D$ in $\cat{C'}$ by
simply composing two functors. The continuity condition for $F$
states that, if the diagram $D$ has a limit $\Lim[D]$, then
the diagram $F \circ D$ also has a limit, and it is equal to
$F (\Lim[D])$.

\begin{figure}[H]
  \centering
  \includegraphics[width=0.6\textwidth]{images/continuity.jpg}
\end{figure}

\noindent
Notice that, because functors map morphisms to morphisms, and
compositions to compositions, an image of a cone is always a cone. A
commuting triangle is always mapped to a commuting triangle (functors
preserve composition). The same is true for the factorizing morphisms:
the image of a factorizing morphism is also a factorizing morphism. So
every functor is \emph{almost} continuous. What may go wrong is the
uniqueness condition. The factorizing morphism in $\cat{C'}$ might not be
unique. There may also be other ``better cones'' in $\cat{C'}$ that were
not available in $\cat{C}$.

A hom-functor is an example of a continuous functor. Recall that the
hom-functor, $\cat{C}(a, b)$, is contravariant in the first variable
and covariant in the second. In other words, it's a functor:
\[\cat{C}^\mathit{op} \times \cat{C} \to \Set\]
When its second argument is fixed, the hom-set functor (which becomes
the representable presheaf) maps colimits in $\cat{C}$ to limits in
$\Set$; and when its first argument is fixed, it maps limits to
limits.

In Haskell, a hom-functor is the mapping of any two types to a function
type, so it's just a parameterized function type. When we fix the second
parameter, let's say to \code{String}, we get the contravariant
functor:

\src{snippet17}
Continuity means that when \code{ToString} is applied to a colimit,
for instance a coproduct \code{Either b c}, it will produce a limit;
in this case a product of two function types:

\src{snippet18}
Indeed, any function of \code{Either b c} is implemented as a case
statement with the two cases being serviced by a pair of functions.

Similarly, when we fix the first argument of the hom-set, we get the
familiar reader functor. Its continuity means that, for instance, any
function returning a product is equivalent to a product of functions; in
particular:

\src{snippet19}
I know what you're thinking: You don't need category theory to figure
these things out. And you're right! Still, I find it amazing that such
results can be derived from first principles with no recourse to bits
and bytes, processor architectures, compiler technologies, or even
lambda calculus.

If you're curious where the names ``limit'' and ``continuity'' come
from, they are a generalization of the corresponding notions from
calculus. In calculus limits and continuity are defined in terms of open
neighborhoods. Open sets, which define topology, form a category (a
poset).

\section{Challenges}

\begin{enumerate}
  \tightlist
  \item
        How would you describe a pushout in the category of C++ classes?
  \item
        Show that the limit of the identity functor
        $\mathbf{Id} \Colon \cat{C} \to \cat{C}$ is the initial object.
  \item
        Subsets of a given set form a category. A morphism in that category is
        defined to be an arrow connecting two sets if the first is the subset
        of the second. What is a pullback of two sets in such a category?
        What's a pushout? What are the initial and terminal objects?
  \item
        Can you guess what a coequalizer is?
  \item
        Show that, in a category with a terminal object, a pullback towards
        the terminal object is a product.
  \item
        Similarly, show that a pushout from an initial object (if one exists)
        is the coproduct.
\end{enumerate}
