mirror of
https://github.com/hmemcpy/milewski-ctfp-pdf.git
synced 2024-11-26 03:11:47 +03:00
parent
a967ec3bf7
commit
2d745c6c68
@ -1,20 +1,18 @@
|
||||
\begin{quote}
|
||||
This is part 10 of Categories for Programmers. Previously:
|
||||
\href{https://bartoszmilewski.com/2015/03/13/function-types/}{Function
|
||||
Types}. See the
|
||||
\href{https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/}{Table
|
||||
of Contents}.
|
||||
\end{quote}
|
||||
\lettrine[lhang=0.17]{W}{e talked about} functors as mappings between categories that preserve
|
||||
their structure.
|
||||
|
||||
We talked about functors as mappings between categories that preserve
|
||||
their structure. A functor ``embeds'' one category in another. It may
|
||||
\begin{wrapfigure}[13]{R}{0pt}
|
||||
\raisebox{0pt}[\dimexpr\height-0.75\baselineskip\relax]{
|
||||
\fbox{\includegraphics[width=60mm]{images/1_functors.jpg}}}%
|
||||
\end{wrapfigure}
|
||||
|
||||
\noindent
|
||||
A functor ``embeds'' one category in another. It may
|
||||
collapse multiple things into one, but it never breaks connections. One
|
||||
way of thinking about it is that with a functor we are modeling one
|
||||
category inside another. The source category serves as a model, a
|
||||
blueprint, for some structure that's part of the target category.
|
||||
|
||||
\includegraphics[width=5.31250in]{images/1_functors.jpg}
|
||||
|
||||
There may be many ways of embedding one category in another. Sometimes
|
||||
they are equivalent, sometimes very different. One may collapse the
|
||||
whole source category into one object, another may map every object to a
|
||||
@ -25,78 +23,86 @@ functors --- special mappings that preserve their functorial nature.
|
||||
|
||||
Consider two functors \code{F} and \code{G} between categories
|
||||
\emph{C} and \emph{D}. If you focus on just one object \code{a} in
|
||||
\emph{C}, it is mapped to two objects: \code{F\ a} and \code{G\ a}.
|
||||
A mapping of functors should therefore map \code{F\ a} to
|
||||
\code{G\ a}.
|
||||
\emph{C}, it is mapped to two objects: \code{F a} and \code{G a}.
|
||||
A mapping of functors should therefore map \code{F a} to
|
||||
\code{G a}.
|
||||
|
||||
\includegraphics[width=3.12500in]{images/2_natcomp.jpg}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\fbox{\includegraphics[width=80mm]{images/2_natcomp.jpg}}
|
||||
\end{figure}
|
||||
|
||||
Notice that \code{F\ a} and \code{G\ a} are objects in the same
|
||||
\noindent
|
||||
Notice that \code{F a} and \code{G a} are objects in the same
|
||||
category \emph{D}. Mappings between objects in the same category should
|
||||
not go against the grain of the category. We don't want to make
|
||||
artificial connections between objects. So it's \emph{natural} to use
|
||||
existing connections, namely morphisms. A natural transformation is a
|
||||
selection of morphisms: for every object \code{a}, it picks one
|
||||
morphism from \code{F\ a} to \code{G\ a}. If we call the natural
|
||||
morphism from \code{F a} to \code{G a}. If we call the natural
|
||||
transformation \code{α}, this morphism is called the \newterm{component}
|
||||
of \code{α} at \code{a}, or \code{αa}.
|
||||
of \code{α} at \code{a}, or \code{α\textsubscript{a}}.
|
||||
|
||||
\begin{verbatim}
|
||||
αa :: F a -> G a
|
||||
\end{verbatim}
|
||||
|
||||
Keep in mind that \code{a} is an object in \emph{C} while \code{αa}
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
α\textsubscript{a} :: F a -> G a
|
||||
\end{Verbatim}
|
||||
Keep in mind that \code{a} is an object in \emph{C} while \code{α\textsubscript{a}}
|
||||
is a morphism in \emph{D}.
|
||||
|
||||
If, for some \code{a}, there is no morphism between \code{F\ a} and
|
||||
\code{G\ a} in \emph{D}, there can be no natural transformation
|
||||
If, for some \code{a}, there is no morphism between \code{F a} and
|
||||
\code{G a} in \emph{D}, there can be no natural transformation
|
||||
between \code{F} and \code{G}.
|
||||
|
||||
Of course that's only half of the story, because functors not only map
|
||||
objects, they map morphisms as well. So what does a natural
|
||||
transformation do with those mappings? It turns out that the mapping of
|
||||
morphisms is fixed --- under any natural transformation between F and G,
|
||||
\code{F\ f} must be transformed into \code{G\ f}. What's more, the
|
||||
\code{F f} must be transformed into \code{G f}. What's more, the
|
||||
mapping of morphisms by the two functors drastically restricts the
|
||||
choices we have in defining a natural transformation that's compatible
|
||||
with it. Consider a morphism \code{f} between two objects \code{a}
|
||||
and \code{b} in \emph{C}. It's mapped to two morphisms, \code{F\ f}
|
||||
and \code{G\ f} in \emph{D}:
|
||||
and \code{b} in \emph{C}. It's mapped to two morphisms, \code{F f}
|
||||
and \code{G f} in \emph{D}:
|
||||
|
||||
\begin{verbatim}
|
||||
F f :: F a -> F b
|
||||
G f :: G a -> G b
|
||||
\end{verbatim}
|
||||
|
||||
\begin{wrapfigure}[5]{R}{0pt}
|
||||
\raisebox{0pt}[\dimexpr\height-0.75\baselineskip\relax]{
|
||||
\fbox{\includegraphics[width=40mm]{images/3_naturality.jpg}}}%
|
||||
\end{wrapfigure}
|
||||
\noindent
|
||||
The natural transformation \code{α} provides two additional morphisms
|
||||
that complete the diagram in \emph{D}:
|
||||
|
||||
\begin{verbatim}
|
||||
αa :: F a -> G a
|
||||
αb :: F b -> G b
|
||||
\end{verbatim}
|
||||
|
||||
\includegraphics[width=3.12500in]{images/3_naturality.jpg}
|
||||
|
||||
Now we have two ways of getting from \code{F\ a} to \code{G\ b}. To
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
α\textsubscript{a} :: F a -> G a
|
||||
α\textsubscript{b} :: F b -> G b
|
||||
\end{Verbatim}
|
||||
Now we have two ways of getting from \code{F a} to \code{G b}. To
|
||||
make sure that they are equal, we must impose the \newterm{naturality
|
||||
condition} that holds for any \code{f}:
|
||||
|
||||
\begin{verbatim}
|
||||
G f ∘ αa = αb ∘ F f
|
||||
\end{verbatim}
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
G f ◦ α\textsubscript{a} = α\textsubscript{b} ◦ F f
|
||||
\end{Verbatim}
|
||||
The naturality condition is a pretty stringent requirement. For
|
||||
instance, if the morphism \code{F\ f} is invertible, naturality
|
||||
determines \code{αb} in terms of \code{αa}. It \newterm{transports}
|
||||
\code{αa} along \code{f}:
|
||||
instance, if the morphism \code{F f} is invertible, naturality
|
||||
determines \code{α\textsubscript{b}} in terms of \code{α\textsubscript{a}}. It \newterm{transports}
|
||||
\code{α\textsubscript{a}} along \code{f}:
|
||||
|
||||
\begin{verbatim}
|
||||
αb = (G f) ∘ αa ∘ (F f)-1
|
||||
\end{verbatim}
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
α\textsubscript{b} = (G f) ◦ α\textsubscript{a} ◦ (F f)\textsuperscript{-1}
|
||||
\end{Verbatim}
|
||||
|
||||
\includegraphics[width=3.12500in]{images/4_transport.jpg}
|
||||
\begin{wrapfigure}[7]{R}{0pt}
|
||||
\raisebox{0pt}[\dimexpr\height-0.75\baselineskip\relax]{
|
||||
\fbox{\includegraphics[width=40mm]{images/4_transport.jpg}}}%
|
||||
\end{wrapfigure}
|
||||
|
||||
\noindent
|
||||
If there is more than one invertible morphism between two objects, all
|
||||
these transports have to agree. In general, though, morphisms are not
|
||||
invertible; but you can see that the existence of natural
|
||||
@ -111,8 +117,12 @@ maps objects to morphisms. Because of the naturality condition, one may
|
||||
also say that it maps morphisms to commuting squares --- there is one
|
||||
commuting naturality square in \emph{D} for every morphism in \emph{C}.
|
||||
|
||||
\includegraphics[width=3.12500in]{images/naturality.jpg}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\fbox{\includegraphics[width=60mm]{images/naturality.jpg}}
|
||||
\end{figure}
|
||||
|
||||
\noindent
|
||||
This property of natural transformations comes in very handy in a lot of
|
||||
categorical constructions, which often include commuting diagrams. With
|
||||
a judicious choice of functors, a lot of these commutativity conditions
|
||||
@ -135,29 +145,26 @@ mapping is implemented by a higher order function \code{fmap} (or
|
||||
|
||||
To construct a natural transformation we start with an object, here a
|
||||
type, \code{a}. One functor, \code{F}, maps it to the type
|
||||
\code{F\ a}. Another functor, \code{G}, maps it to \code{G\ a}.
|
||||
\code{F a}. Another functor, \code{G}, maps it to \code{G a}.
|
||||
The component of a natural transformation \code{alpha} at \code{a}
|
||||
is a function from \code{F\ a} to \code{G\ a}. In pseudo-Haskell:
|
||||
|
||||
\begin{verbatim}
|
||||
alphaa :: F a -> G a
|
||||
\end{verbatim}
|
||||
is a function from \code{F a} to \code{G a}. In pseudo-Haskell:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
alpha\textsubscript{a} :: F a -> G a
|
||||
\end{Verbatim}
|
||||
A natural transformation is a polymorphic function that is defined for
|
||||
all types \code{a}:
|
||||
|
||||
\begin{verbatim}
|
||||
alpha :: forall a . F a -> G a
|
||||
\end{verbatim}
|
||||
|
||||
The \code{forall\ a} is optional in Haskell (and in fact requires
|
||||
The \code{forall a} is optional in Haskell (and in fact requires
|
||||
turning on the language extension \code{ExplicitForAll}). Normally,
|
||||
you would write it like this:
|
||||
|
||||
\begin{verbatim}
|
||||
alpha :: F a -> G a
|
||||
\end{verbatim}
|
||||
|
||||
Keep in mind that it's really a family of functions parameterized by
|
||||
\code{a}. This is another example of the terseness of the Haskell
|
||||
syntax. A similar construct in C++ would be slightly more verbose:
|
||||
@ -165,14 +172,13 @@ syntax. A similar construct in C++ would be slightly more verbose:
|
||||
\begin{verbatim}
|
||||
template<class A> G<A> alpha(F<A>);
|
||||
\end{verbatim}
|
||||
|
||||
There is a more profound difference between Haskell's polymorphic
|
||||
functions and C++ generic functions, and it's reflected in the way these
|
||||
functions are implemented and type-checked. In Haskell, a polymorphic
|
||||
function must be defined uniformly for all types. One formula must work
|
||||
across all types. This is called \newterm{parametric polymorphism}.
|
||||
|
||||
C++, on the other hand, supports by default~\newterm{ad hoc polymorphism},
|
||||
C++, on the other hand, supports by default \newterm{ad hoc polymorphism},
|
||||
which means that a template doesn't have to be well-defined for all
|
||||
types. Whether a template will work for a given type is decided at
|
||||
instantiation time, where a concrete type is substituted for the type
|
||||
@ -190,30 +196,26 @@ polymorphic function of the type:
|
||||
\begin{verbatim}
|
||||
alpha :: F a -> G a
|
||||
\end{verbatim}
|
||||
|
||||
where \code{F} and \code{G} are functors, automatically satisfies
|
||||
the naturality condition. Here it is in categorical notation (\code{f}
|
||||
is a function \code{f::a->b}):
|
||||
|
||||
\begin{verbatim}
|
||||
G f ∘ αa = αb ∘ F f
|
||||
\end{verbatim}
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
G f ◦ α\textsubscript{a} = α\textsubscript{b} ◦ F f
|
||||
\end{Verbatim}
|
||||
In Haskell, the action of a functor \code{G} on a morphism \code{f}
|
||||
is implemented using \code{fmap}. I'll first write it in
|
||||
pseudo-Haskell, with explicit type annotations:
|
||||
|
||||
\begin{verbatim}
|
||||
fmapG f . alphaa = alphab . fmapF f
|
||||
\end{verbatim}
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
fmap\textsubscript{G} f . alpha\textsubscript{a} = alpha\textsubscript{b} . fmap\textsubscript{F} f
|
||||
\end{Verbatim}
|
||||
Because of type inference, these annotations are not necessary, and the
|
||||
following equation holds:
|
||||
|
||||
\begin{verbatim}
|
||||
fmap f . alpha = alpha . fmap f
|
||||
\end{verbatim}
|
||||
|
||||
This is still not real Haskell --- function equality is not expressible
|
||||
in code --- but it's an identity that can be used by the programmer in
|
||||
equational reasoning; or by the compiler, to implement optimizations.
|
||||
@ -224,10 +226,10 @@ define natural transformations in Haskell, imposes very strong
|
||||
limitations on the implementation --- one formula for all types. These
|
||||
limitations translate into equational theorems about such functions. In
|
||||
the case of functions that transform functors, free theorems are the
|
||||
naturality conditions. {[}You may read more about free theorems in my
|
||||
blog
|
||||
\href{https://bartoszmilewski.com/2014/09/22/parametricity-money-for-nothing-and-theorems-for-free/}{Parametricity:
|
||||
Money for Nothing and Theorems for Free}.{]}
|
||||
naturality conditions.\footnote{
|
||||
You may read more about free theorems in my
|
||||
blog \href{https://bartoszmilewski.com/2014/09/22/parametricity-money-for-nothing-and-theorems-for-free/}{Parametricity:
|
||||
Money for Nothing and Theorems for Free}.}
|
||||
|
||||
One way of thinking about functors in Haskell that I mentioned earlier
|
||||
is to consider them generalized containers. We can continue this analogy
|
||||
@ -253,7 +255,6 @@ safeHead :: [a] -> Maybe a
|
||||
safeHead [] = Nothing
|
||||
safeHead (x:xs) = Just x
|
||||
\end{verbatim}
|
||||
|
||||
It's a function polymorphic in \code{a}. It works for any type
|
||||
\code{a}, with no limitations, so it is an example of parametric
|
||||
polymorphism. Therefore it is a natural transformation between the two
|
||||
@ -263,7 +264,6 @@ condition.
|
||||
\begin{verbatim}
|
||||
fmap f . safeHead = safeHead . fmap f
|
||||
\end{verbatim}
|
||||
|
||||
We have two cases to consider; an empty list:
|
||||
|
||||
\begin{verbatim}
|
||||
@ -273,45 +273,39 @@ fmap f (safeHead []) = fmap f Nothing = Nothing
|
||||
\begin{verbatim}
|
||||
safeHead (fmap f []) = safeHead [] = Nothing
|
||||
\end{verbatim}
|
||||
|
||||
and a non-empty list:
|
||||
|
||||
\begin{verbatim}
|
||||
fmap f (safeHead (x:xs)) = fmap f (Just x) = Just (f x)
|
||||
\end{verbatim}
|
||||
|
||||
\begin{verbatim}
|
||||
\begin{minted}[breaklines]{text}
|
||||
safeHead (fmap f (x:xs)) = safeHead (f x : fmap f xs) = Just (f x)
|
||||
\end{verbatim}
|
||||
|
||||
\end{minted}
|
||||
I used the implementation of \code{fmap} for lists:
|
||||
|
||||
\begin{verbatim}
|
||||
fmap f [] = []
|
||||
fmap f (x:xs) = f x : fmap f xs
|
||||
\end{verbatim}
|
||||
|
||||
and for \code{Maybe}:
|
||||
|
||||
\begin{verbatim}
|
||||
fmap f Nothing = Nothing
|
||||
fmap f (Just x) = Just (f x)
|
||||
\end{verbatim}
|
||||
|
||||
An interesting case is when one of the functors is the trivial
|
||||
\code{Const} functor. A natural transformation from or to a
|
||||
\code{Const} functor looks just like a function that's either
|
||||
polymorphic in its return type or in its argument type.
|
||||
|
||||
For instance, \code{length} can be thought of as a natural
|
||||
transformation from the list functor to the \code{Const\ Int} functor:
|
||||
transformation from the list functor to the \code{Const Int} functor:
|
||||
|
||||
\begin{verbatim}
|
||||
length :: [a] -> Const Int a
|
||||
length [] = Const 0
|
||||
length (x:xs) = Const (1 + unConst (length xs))
|
||||
\end{verbatim}
|
||||
|
||||
Here, \code{unConst} is used to peel off the \code{Const}
|
||||
constructor:
|
||||
|
||||
@ -319,13 +313,11 @@ constructor:
|
||||
unConst :: Const c a -> c
|
||||
unConst (Const x) = x
|
||||
\end{verbatim}
|
||||
|
||||
Of course, in practice \code{length} is defined as:
|
||||
|
||||
\begin{verbatim}
|
||||
length :: [a] -> Int
|
||||
\end{verbatim}
|
||||
|
||||
which effectively hides the fact that it's a natural transformation.
|
||||
|
||||
Finding a parametrically polymorphic function \emph{from} a
|
||||
@ -336,7 +328,6 @@ creation of a value from nothing. The best we can do is:
|
||||
scam :: Const Int a -> Maybe a
|
||||
scam (Const x) = Nothing
|
||||
\end{verbatim}
|
||||
|
||||
Another common functor that we've seen already, and which will play an
|
||||
important role in the Yoneda lemma, is the \code{Reader} functor. I
|
||||
will rewrite its definition as a \code{newtype}:
|
||||
@ -344,20 +335,18 @@ will rewrite its definition as a \code{newtype}:
|
||||
\begin{verbatim}
|
||||
newtype Reader e a = Reader (e -> a)
|
||||
\end{verbatim}
|
||||
|
||||
It is parameterized by two types, but is (covariantly) functorial only
|
||||
in the second one:
|
||||
|
||||
\begin{verbatim}
|
||||
instance Functor (Reader e) where fmap f (Reader g) = Reader (\x -> f (g x))
|
||||
instance Functor (Reader e) where
|
||||
fmap f (Reader g) = Reader (\x -> f (g x))
|
||||
\end{verbatim}
|
||||
|
||||
For every type \code{e}, you can define a family of natural
|
||||
transformations from \code{Reader\ e} to any other functor \code{f}.
|
||||
We'll see later that the members of this family are always in one to one
|
||||
correspondence with the elements of \code{f\ e} (the
|
||||
\href{https://bartoszmilewski.com/2015/09/01/the-yoneda-lemma/}{Yoneda
|
||||
lemma}).
|
||||
correspondence with the elements of \code{f e} (the
|
||||
\hyperref[the-yoneda-lemma]{Yoneda lemma}).
|
||||
|
||||
For instance, consider the somewhat trivial unit type \code{()} with
|
||||
one element \code{()}. The functor \code{Reader\ ()} takes any type
|
||||
@ -370,25 +359,22 @@ to the \code{Maybe} functor:
|
||||
\begin{verbatim}
|
||||
alpha :: Reader () a -> Maybe a
|
||||
\end{verbatim}
|
||||
|
||||
There are only two of these, \code{dumb} and \code{obvious}:
|
||||
|
||||
\begin{verbatim}
|
||||
dumb (Reader _) = Nothing
|
||||
\end{verbatim}
|
||||
|
||||
and
|
||||
|
||||
\begin{verbatim}
|
||||
obvious (Reader g) = Just (g ())
|
||||
\end{verbatim}
|
||||
|
||||
(The only thing you can do with \code{g} is to apply it to the unit
|
||||
value \code{()}.)
|
||||
|
||||
And, indeed, as predicted by the Yoneda lemma, these correspond to the
|
||||
two elements of the \code{Maybe\ ()} type, which are \code{Nothing}
|
||||
and \code{Just\ ()}. We'll come back to the Yoneda lemma later ---
|
||||
two elements of the \code{Maybe ()} type, which are \code{Nothing}
|
||||
and \code{Just ()}. We'll come back to the Yoneda lemma later ---
|
||||
this was just a little teaser.
|
||||
|
||||
\section{Beyond Naturality}\label{beyond-naturality}
|
||||
@ -416,20 +402,18 @@ at before:
|
||||
\begin{verbatim}
|
||||
newtype Op r a = Op (a -> r)
|
||||
\end{verbatim}
|
||||
|
||||
This functor is contravariant in \code{a}:
|
||||
|
||||
\begin{verbatim}
|
||||
instance Contravariant (Op r) where contramap f (Op g) = Op (g . f)
|
||||
instance Contravariant (Op r) where
|
||||
contramap f (Op g) = Op (g . f)
|
||||
\end{verbatim}
|
||||
|
||||
We can write a polymorphic function from, say, \code{Op\ Bool} to
|
||||
\code{Op\ String}:
|
||||
We can write a polymorphic function from, say, \code{Op Bool} to
|
||||
\code{Op String}:
|
||||
|
||||
\begin{verbatim}
|
||||
predToStr (Op f) = Op (\x -> if f x then "T" else "F")
|
||||
\end{verbatim}
|
||||
|
||||
But since the two functors are not covariant, this is not a natural
|
||||
transformation in \textbf{Hask}. However, because they are both
|
||||
contravariant, they satisfy the ``opposite'' naturality condition:
|
||||
@ -437,7 +421,6 @@ contravariant, they satisfy the ``opposite'' naturality condition:
|
||||
\begin{verbatim}
|
||||
contramap f . predToStr = predToStr . contramap f
|
||||
\end{verbatim}
|
||||
|
||||
Notice that the function \code{f} must go in the opposite direction
|
||||
than what you'd use with \code{fmap}, because of the signature of
|
||||
\code{contramap}:
|
||||
@ -445,14 +428,12 @@ than what you'd use with \code{fmap}, because of the signature of
|
||||
\begin{verbatim}
|
||||
contramap :: (b -> a) -> (Op Bool a -> Op Bool b)
|
||||
\end{verbatim}
|
||||
|
||||
Are there any type constructors that are not functors, whether covariant
|
||||
or contravariant? Here's one example:
|
||||
|
||||
\begin{verbatim}
|
||||
a -> a
|
||||
\end{verbatim}
|
||||
|
||||
This is not a functor because the same type \code{a} is used both in
|
||||
the negative (contravariant) and positive (covariant) position. You
|
||||
can't implement \code{fmap} or \code{contramap} for this type.
|
||||
@ -461,7 +442,6 @@ Therefore a function of the signature:
|
||||
\begin{verbatim}
|
||||
(a -> a) -> f a
|
||||
\end{verbatim}
|
||||
|
||||
where \code{f} is an arbitrary functor, cannot be a natural
|
||||
transformation. Interestingly, there is a generalization of natural
|
||||
transformations, called dinatural transformations, that deals with such
|
||||
@ -483,42 +463,47 @@ we know how to compose morphisms.
|
||||
Indeed, let's take a natural transformation α from functor F to G. Its
|
||||
component at object \code{a} is some morphism:
|
||||
|
||||
\begin{verbatim}
|
||||
αa :: F a -> G a
|
||||
\end{verbatim}
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
α\textsubscript{a} :: F a -> G a
|
||||
\end{Verbatim}
|
||||
We'd like to compose α with β, which is a natural transformation from
|
||||
functor G to H. The component of β at \code{a} is a morphism:
|
||||
|
||||
\begin{verbatim}
|
||||
βa :: G a -> H a
|
||||
\end{verbatim}
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
β\textsubscript{a} :: G a -> H a
|
||||
\end{Verbatim}
|
||||
These morphisms are composable and their composition is another
|
||||
morphism:
|
||||
|
||||
\begin{verbatim}
|
||||
βa ∘ αa :: F a -> H a
|
||||
\end{verbatim}
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
β\textsubscript{a} ◦ α\textsubscript{a} :: F a -> H a
|
||||
\end{Verbatim}
|
||||
We will use this morphism as the component of the natural transformation
|
||||
β ⋅ α --- the composition of two natural transformations β after α:
|
||||
|
||||
\begin{verbatim}
|
||||
(β ⋅ α)a = βa ∘ αa
|
||||
\end{verbatim}
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
(β \ensuremath{⋅} α)a = β\textsubscript{a} ◦ α\textsubscript{a}
|
||||
\end{Verbatim}
|
||||
|
||||
\includegraphics[width=3.12500in]{images/5_vertical.jpg}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\fbox{\includegraphics[width=60mm]{images/5_vertical.jpg}}
|
||||
\end{figure}
|
||||
|
||||
\noindent
|
||||
One (long) look at a diagram convinces us that the result of this
|
||||
composition is indeed a natural transformation from F to H:
|
||||
|
||||
\begin{verbatim}
|
||||
H f ∘ (β ⋅ α)a = (β ⋅ α)b ∘ F f
|
||||
\end{verbatim}
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
H f ◦ (β \ensuremath{⋅} α)\textsubscript{a} = (β \ensuremath{⋅} α)\textsubscript{b} ◦ F f
|
||||
\end{Verbatim}
|
||||
|
||||
\includegraphics[width=3.12500in]{images/6_verticalnaturality.jpg}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\fbox{\includegraphics[width=60mm]{images/6_verticalnaturality.jpg}}
|
||||
\end{figure}
|
||||
|
||||
\noindent
|
||||
Composition of natural transformations is associative, because their
|
||||
components, which are regular morphisms, are associative with respect to
|
||||
their composition.
|
||||
@ -526,10 +511,9 @@ their composition.
|
||||
Finally, for each functor F there is an identity natural transformation
|
||||
1\textsubscript{F} whose components are the identity morphisms:
|
||||
|
||||
\begin{verbatim}
|
||||
idF a :: F a -> F a
|
||||
\end{verbatim}
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
id\textsubscript{F a} :: F a -> F a
|
||||
\end{Verbatim}
|
||||
So, indeed, functors form a category.
|
||||
|
||||
A word about notation. Following Saunders Mac Lane I use the dot for the
|
||||
@ -540,10 +524,13 @@ usually stacked up vertically in the diagrams that describe it. Vertical
|
||||
composition is important in defining the functor category. I'll explain
|
||||
horizontal composition shortly.
|
||||
|
||||
\includegraphics[width=2.29167in]{images/6a_vertical.jpg}
|
||||
\begin{figure}
|
||||
\centering
|
||||
\fbox{\includegraphics[width=60mm]{images/6a_vertical.jpg}}
|
||||
\end{figure}
|
||||
|
||||
The functor category between categories C and D is written as
|
||||
\code{Fun(C,\ D)}, or \code{{[}C,\ D{]}}, or sometimes as
|
||||
\code{Fun(C, D)}, or \code{{[}C, D{]}}, or sometimes as
|
||||
\code{DC}. This last notation suggests that a functor category itself
|
||||
might be considered a function object (an exponential) in some other
|
||||
category. Is this indeed the case?
|
||||
@ -556,7 +543,10 @@ in a higher-level category \textbf{Cat}. Morphisms in that category are
|
||||
functors. A Hom-set in \textbf{Cat} is a set of functors. For instance
|
||||
Cat(C, D) is a set of functors between two categories C and D.
|
||||
|
||||
\includegraphics[width=2.23958in]{images/7_cathomset.jpg}
|
||||
\begin{figure}
|
||||
\centering
|
||||
\fbox{\includegraphics[width=60mm]{images/7_cathomset.jpg}}
|
||||
\end{figure}
|
||||
|
||||
A functor category {[}C, D{]} is also a set of functors between two
|
||||
categories (plus natural transformations as morphisms). Its objects are
|
||||
@ -572,12 +562,12 @@ As you may remember, in order to construct an exponential, we need to
|
||||
first define a product. In \textbf{Cat}, this turns out to be relatively
|
||||
easy, because small categories are \emph{sets} of objects, and we know
|
||||
how to define cartesian products of sets. So an object in a product
|
||||
category C × D is just a pair of objects, \code{(c,\ d)}, one from C
|
||||
category C × D is just a pair of objects, \code{(c, d)}, one from C
|
||||
and one from D. Similarly, a morphism between two such pairs,
|
||||
\code{(c,\ d)} and \code{(c\',\ d\')}, is a pair of
|
||||
morphisms, \code{(f,\ g)}, where
|
||||
\code{f\ ::\ c\ ->\ c\'} and
|
||||
\code{g\ ::\ d\ ->\ d\'}. These pairs of morphisms
|
||||
\code{(c, d)} and \code{(c', d')}, is a pair of
|
||||
morphisms, \code{(f, g)}, where
|
||||
\code{f :: c -> c'} and
|
||||
\code{g :: d -> d'}. These pairs of morphisms
|
||||
compose component-wise, and there is always an identity pair that is
|
||||
just a pair of identity morphisms. To make the long story short,
|
||||
\textbf{Cat} is a full-blown cartesian closed category in which there is
|
||||
@ -612,6 +602,12 @@ In the case of \textbf{Cat} seen as a 2-category we have:
|
||||
2-morphisms: Natural transformations between functors.
|
||||
\end{itemize}
|
||||
|
||||
\begin{wrapfigure}[11]{R}{0pt}
|
||||
\raisebox{0pt}[\dimexpr\height-0.75\baselineskip\relax]{
|
||||
\fbox{\includegraphics[width=2.25000in]{images/8_cat-2-cat.jpg}}}%
|
||||
\end{wrapfigure}
|
||||
|
||||
\noindent
|
||||
Instead of a Hom-set between two categories C and D, we have a
|
||||
Hom-category --- the functor category D\textsuperscript{C}. We have
|
||||
regular functor composition: a functor F from D\textsuperscript{C}
|
||||
@ -620,8 +616,7 @@ E\textsuperscript{C}. But we also have composition inside each
|
||||
Hom-category --- vertical composition of natural transformations, or
|
||||
2-morphisms, between functors.
|
||||
|
||||
\includegraphics[width=2.25000in]{images/8_cat-2-cat.jpg}
|
||||
|
||||
\noindent
|
||||
With two kinds of composition in a 2-category, the question arises: How
|
||||
do they interact with each other?
|
||||
|
||||
@ -631,13 +626,11 @@ Let's pick two functors, or 1-morphisms, in \textbf{Cat}:
|
||||
F :: C -> D
|
||||
G :: D -> E
|
||||
\end{verbatim}
|
||||
|
||||
and their composition:
|
||||
|
||||
\begin{verbatim}
|
||||
G ∘ F :: C -> E
|
||||
G ◦ F :: C -> E
|
||||
\end{verbatim}
|
||||
|
||||
Suppose we have two natural transformations, α and β, that act,
|
||||
respectively, on functors F and G:
|
||||
|
||||
@ -646,8 +639,12 @@ respectively, on functors F and G:
|
||||
β :: G -> G'
|
||||
\end{verbatim}
|
||||
|
||||
\includegraphics[width=3.12500in]{images/10_horizontal.jpg}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\fbox{\includegraphics[width=60mm]{images/10_horizontal.jpg}}
|
||||
\end{figure}
|
||||
|
||||
\noindent
|
||||
Notice that we cannot apply vertical composition to this pair, because
|
||||
the target of α is different from the source of β. In fact they are
|
||||
members of two different functor categories: D \textsuperscript{C} and E
|
||||
@ -658,50 +655,49 @@ category D. What's the relation between the functors G'∘ F' and G ∘ F?
|
||||
Having α and β at our disposal, can we define a natural transformation
|
||||
from G ∘ F to G'∘ F'? Let me sketch the construction.
|
||||
|
||||
\includegraphics[width=3.84375in]{images/9_horizontal.jpg}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\fbox{\includegraphics[width=90mm]{images/9_horizontal.jpg}}
|
||||
\end{figure}
|
||||
|
||||
\noindent
|
||||
As usual, we start with an object \code{a} in C. Its image splits into
|
||||
two objects in D: \code{F\ a} and \code{F\'a}. There is also a
|
||||
two objects in D: \code{F a} and \code{F'a}. There is also a
|
||||
morphism, a component of α, connecting these two objects:
|
||||
|
||||
\begin{verbatim}
|
||||
αa :: F a -> F'a
|
||||
\end{verbatim}
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
α\textsubscript{a} :: F a -> F'a
|
||||
\end{Verbatim}
|
||||
When going from D to E, these two objects split further into four
|
||||
objects:
|
||||
|
||||
\begin{verbatim}
|
||||
G (F a), G'(F a), G (F'a), G'(F'a)
|
||||
\end{verbatim}
|
||||
|
||||
We also have four morphisms forming a square. Two of these morphisms are
|
||||
the components of the natural transformation β:
|
||||
|
||||
\begin{verbatim}
|
||||
βF a :: G (F a) -> G'(F a)
|
||||
βF'a :: G (F'a) -> G'(F'a)
|
||||
\end{verbatim}
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
β\textsubscript{F a} :: G (F a) -> G'(F a)
|
||||
β\textsubscript{F'a} :: G (F'a) -> G'(F'a)
|
||||
\end{Verbatim}
|
||||
The other two are the images of α\textsubscript{a} under the two
|
||||
functors (functors map morphisms):
|
||||
|
||||
\begin{verbatim}
|
||||
G αa :: G (F a) -> G (F'a)
|
||||
G'αa :: G'(F a) -> G'(F'a)
|
||||
\end{verbatim}
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
G α\textsubscript{a} :: G (F a) -> G (F'a)
|
||||
G'α\textsubscript{a} :: G'(F a) -> G'(F'a)
|
||||
\end{Verbatim}
|
||||
That's a lot of morphisms. Our goal is to find a morphism that goes from
|
||||
\code{G\ (F\ a)} to \code{G\'(F\'a)}, a candidate for the
|
||||
\code{G (F a)} to \code{G'(F'a)}, a candidate for the
|
||||
component of a natural transformation connecting the two functors G ∘ F
|
||||
and G'∘ F'. In fact there's not one but two paths we can take from
|
||||
\code{G\ (F\ a)} to \code{G\'(F\'a)}:
|
||||
|
||||
\begin{verbatim}
|
||||
G'αa ∘ βF a
|
||||
βF'a ∘ G αa
|
||||
\end{verbatim}
|
||||
\code{G (F a)} to \code{G'(F'a)}:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
G'α\textsubscript{a} ◦ β\textsubscript{F a}
|
||||
β\textsubscript{F'a} ◦ G α\textsubscript{a}
|
||||
\end{Verbatim}
|
||||
Luckily for us, they are equal, because the square we have formed turns
|
||||
out to be the naturality square for β.
|
||||
|
||||
@ -713,9 +709,8 @@ We call this natural transformation the \newterm{horizontal composition} of
|
||||
α and β:
|
||||
|
||||
\begin{verbatim}
|
||||
β ∘ α :: G ∘ F -> G'∘ F'
|
||||
β ◦ α :: G ◦ F -> G' ◦ F'
|
||||
\end{verbatim}
|
||||
|
||||
Again, following Mac Lane I use the small circle for horizontal
|
||||
composition, although you may also encounter star in its place.
|
||||
|
||||
@ -730,8 +725,12 @@ between categories. A natural transformation sits between two
|
||||
categories, the ones that are connected by the functors it transforms.
|
||||
We can think of it as connecting these two categories.
|
||||
|
||||
\includegraphics[width=3.12500in]{images/sideways.jpg}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\fbox{\includegraphics[width=60mm]{images/sideways.jpg}}
|
||||
\end{figure}
|
||||
|
||||
\noindent
|
||||
Let's focus on two objects of \textbf{Cat} --- categories C and D. There
|
||||
is a set of natural transformations that go between functors that
|
||||
connect C to D. These natural transformations are our new arrows from C
|
||||
@ -762,9 +761,8 @@ transformation acting on this functor. So you'll often see this
|
||||
notation:
|
||||
|
||||
\begin{verbatim}
|
||||
F ∘ α
|
||||
F ◦ α
|
||||
\end{verbatim}
|
||||
|
||||
where F is a functor from D to E, and α is a natural transformation
|
||||
between two functors going from C to D. Since you can't compose a
|
||||
functor with a natural transformation, this is interpreted as a
|
||||
@ -774,9 +772,8 @@ horizontal composition of the identity natural transformation
|
||||
Similarly:
|
||||
|
||||
\begin{verbatim}
|
||||
α ∘ F
|
||||
α ◦ F
|
||||
\end{verbatim}
|
||||
|
||||
is a horizontal composition of α after 1\textsubscript{F}.
|
||||
|
||||
\section{Conclusion}\label{conclusion}
|
||||
@ -808,15 +805,16 @@ natural transformation is a special type of polymorphic function.
|
||||
\section{Challenges}\label{challenges}
|
||||
|
||||
\begin{enumerate}
|
||||
\tightlist
|
||||
\item
|
||||
Define a natural transformation from the \code{Maybe} functor to the
|
||||
list functor. Prove the naturality condition for it.
|
||||
\item
|
||||
Define at least two different natural transformations between
|
||||
\code{Reader\ ()} and the list functor. How many different lists of
|
||||
\code{Reader ()} and the list functor. How many different lists of
|
||||
\code{()} are there?
|
||||
\item
|
||||
Continue the previous exercise with \code{Reader\ Bool} and
|
||||
Continue the previous exercise with \code{Reader Bool} and
|
||||
\code{Maybe}.
|
||||
\item
|
||||
Show that horizontal composition of natural transformation satisfies
|
||||
@ -842,13 +840,3 @@ f :: String -> Int
|
||||
f x = read x
|
||||
\end{verbatim}
|
||||
\end{enumerate}
|
||||
|
||||
Next:
|
||||
\href{https://bartoszmilewski.com/2015/04/15/category-theory-and-declarative-programming/}{Declarative
|
||||
Programming}.
|
||||
|
||||
\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.\\
|
||||
\href{https://twitter.com/BartoszMilewski}{Follow @BartoszMilewski}
|
||||
|
@ -1,4 +1,4 @@
|
||||
The Ancient Greek playwright Euripides once said: ``Every man is like
|
||||
\lettrine[lhang=0.17]{T}{he Ancient Greek} playwright Euripides once said: ``Every man is like
|
||||
the company he is wont to keep.'' We are defined by our relationships.
|
||||
Nowhere is this more true than in category theory. If we want to single
|
||||
out a particular object in a category, we can only do this by describing
|
||||
|
@ -795,9 +795,9 @@ object to itself, and every morphism to itself. So functors have all the
|
||||
same properties as morphisms in some category. But what category would
|
||||
that be? It would have to be a category in which objects are categories
|
||||
and morphisms are functors. It's a category of categories. But a
|
||||
category of \newterm{all} categories would have to include itself, and we
|
||||
category of \emph{all} categories would have to include itself, and we
|
||||
would get into the same kinds of paradoxes that made the set of all sets
|
||||
impossible. There is, however, a category of all \newterm{small} categories
|
||||
impossible. There is, however, a category of all \emph{small} categories
|
||||
called \textbf{Cat} (which is big, so it can't be a member of itself). A
|
||||
small category is one in which objects form a set, as opposed to
|
||||
something larger than a set. Mind you, in category theory, even an
|
||||
|
@ -1,4 +1,4 @@
|
||||
Now that you know what a functor is, and have seen a few examples, let's
|
||||
\lettrine[lhang=0.17]{N}{ow that you} know what a functor is, and have seen a few examples, let's
|
||||
see how we can build larger functors from smaller ones. In particular
|
||||
it's interesting to see which type constructors (which correspond to
|
||||
mappings between objects in a category) can be extended to functors
|
||||
@ -639,7 +639,7 @@ the defaults for \code{lmap} and \code{rmap}, or implementing both
|
||||
\code{lmap} and \code{rmap} and accepting the default for
|
||||
\code{dimap}.
|
||||
|
||||
\begin{figure}
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\fbox{\includegraphics[width=60mm]{images/dimap.jpg}}
|
||||
\caption{dimap}
|
||||
|
@ -1,4 +1,4 @@
|
||||
So far I've been glossing over the meaning of function types. A function
|
||||
\lettrine[lhang=0.17]{S}{o far I've} been glossing over the meaning of function types. A function
|
||||
type is different from other types.
|
||||
|
||||
\begin{wrapfigure}[13]{R}{0pt}
|
||||
@ -111,7 +111,7 @@ That's when we apply our secret weapon: ranking. This is usually done by
|
||||
requiring that there be a unique mapping between candidate objects --- a
|
||||
mapping that somehow factorizes our construction. In our case, we'll
|
||||
decree that \code{z} together with the morphism \code{g} from
|
||||
\code{z×a} to \code{b} is \newterm{better} than some other
|
||||
\code{z×a} to \code{b} is \emph{better} than some other
|
||||
\code{z'} with its own application \code{g'}, if and
|
||||
only if there is a unique mapping \code{h} from \code{z'} to
|
||||
\code{z} such that the application of \code{g'} factors
|
||||
|
@ -114,6 +114,9 @@ PDF compiled by @url{https://github.com/hmemcpy/milewski-ctfp-pdf, Igal Tabachni
|
||||
\chapter{Function Types}
|
||||
\subfile{content/1.9/Function Types}
|
||||
|
||||
\chapter{Natural Transformations}
|
||||
\subfile{content/1.10/Natural Transformations}
|
||||
|
||||
\backmatter
|
||||
|
||||
@unnumbered Acknowledgments
|
||||
|
Loading…
Reference in New Issue
Block a user