More style tweaks for chapters 1.3 and 1.4

This commit is contained in:
Igal Tabachnik 2017-09-24 09:17:35 +03:00
parent 2662dd8b6e
commit a0bd6ef215
3 changed files with 84 additions and 121 deletions

BIN
ctfp.pdf

Binary file not shown.

View File

@ -90,7 +90,6 @@ Associativity means that:
\begin{verbatim}
(a + b) + c = a + (b + c)
\end{verbatim}
(In other words, we can skip parentheses when adding numbers.)
The neutral element is zero, because:
@ -98,13 +97,11 @@ The neutral element is zero, because:
\begin{verbatim}
0 + a = a
\end{verbatim}
and
\begin{verbatim}
a + 0 = a
\end{verbatim}
The second equation is redundant, because addition is commutative \code{(a + b
= b + a)}, but commutativity is not part of the definition of a monoid.
For instance, string concatenation is not commutative and yet it forms a
@ -116,12 +113,11 @@ In Haskell we can define a type class for monoids --- a type for which
there is a neutral element called \code{mempty} and a binary operation
called \code{mappend}:
\begin{minted}{haskell}
\begin{verbatim}
class Monoid m where
mempty :: m
mappend :: m -> m -> m
\end{minted}
\end{verbatim}
The type signature for a two-argument function,
\code{m->m->m}, might look strange at first,
but it will make perfect sense after we talk about currying. You may
@ -147,12 +143,11 @@ be a monoid by providing the implementation of \code{mempty} and
\code{mappend} (this is, in fact, done for you in the standard
Prelude):
\begin{minted}{haskell}
\begin{verbatim}
instance Monoid String where
mempty = ""
mappend = (++)
\end{minted}
\end{verbatim}
Here, we have reused the list concatenation operator \code{(++)},
because a \code{String} is just a list of characters.
@ -160,16 +155,14 @@ A word about Haskell syntax: Any infix operator can be turned into a
two-argument function by surrounding it with parentheses. Given two
strings, you can concatenate them by inserting \code{++} between them:
\begin{minted}{haskell}
\begin{verbatim}
"Hello " ++ "world!"
\end{minted}
\end{verbatim}
or by passing them as two arguments to the parenthesized \code{(++)}:
\begin{minted}{haskell}
\begin{verbatim}
(++) "Hello " "world!"
\end{minted}
\end{verbatim}
Notice that arguments to a function are not separated by commas or
surrounded by parentheses. (This is probably the hardest thing to get
used to when learning Haskell.)
@ -177,17 +170,15 @@ used to when learning Haskell.)
It's worth emphasizing that Haskell lets you express equality of
functions, as in:
\begin{minted}{haskell}
\begin{verbatim}
mappend = (++)
\end{minted}
\end{verbatim}
Conceptually, this is different than expressing the equality of values
produced by functions, as in:
\begin{minted}{haskell}
\begin{verbatim}
mappend s1 s2 = (++) s1 s2
\end{minted}
\end{verbatim}
The former translates into equality of morphisms in the category
\textbf{Hask} (or \textbf{Set}, if we ignore bottoms, which is the name
for never-ending calculations). Such equations are not only more
@ -204,7 +195,7 @@ so this might be a little confusing to the beginner.)
The closest one can get to declaring a monoid in C++ would be to use the
(proposed) syntax for concepts.
\begin{minted}{c++}
\begin{verbatim}
template<class T>
T mempty = delete;
@ -216,9 +207,7 @@ template<class M>
{ mempty<M> } -> M;
{ mappend(m, m); } -> M;
};
\end{minted}
\end{verbatim}
The first definition uses a value template (also proposed). A
polymorphic value is a family of values --- a different value for every
type.
@ -234,14 +223,14 @@ type) that tests whether there exist appropriate definitions of
An instantiation of the Monoid concept can be accomplished by providing
appropriate specializations and overloads:
\begin{minted}{c++}
\begin{verbatim}
template<>
std::string mempty<std::string> = {""};
std::string mappend(std::string s1, std::string s2) {
return s1 + s2;
}
\end{minted}
\end{verbatim}
\section{Monoid as Category}\label{monoid-as-category}
@ -287,8 +276,8 @@ morphisms that follow appropriate rules of composition.
\begin{figure}
\centering
\fbox{\includegraphics[width=2.45833in]{images/monoid.jpg}}
\centering
\fbox{\includegraphics[width=2.45833in]{images/monoid.jpg}}
\end{figure}
String concatenation is an interesting case, because we have a choice of
@ -315,10 +304,10 @@ this product. So we can always recover a set monoid from a category
monoid. For all intents and purposes they are one and the same.
\begin{figure}
\centering
\includegraphics[width=3.12500in]{images/monoidhomset.jpg}
\captionsetup{labelformat=empty,font=scriptsize}
\caption{Monoid hom-set seen as morphisms and as points in a set.}
\centering
\includegraphics[width=3.12500in]{images/monoidhomset.jpg}
\captionsetup{labelformat=empty,font=scriptsize}
\caption{Monoid hom-set seen as morphisms and as points in a set.}
\end{figure}
There is just one little nit for mathematicians to pick: morphisms don't
@ -341,6 +330,7 @@ according to his and Bjarne Stroustrup's latest proposal.
\section{Challenges}\label{challenges}
\begin{enumerate}
\tightlist
\item
Generate a free category from:

View File

@ -5,15 +5,14 @@ functions that log or trace their execution. Something that, in an
imperative language, would likely be implemented by mutating some global
state, as in:
\begin{minted}{c++}
\begin{verbatim}
string logger;
bool negate(bool b) {
logger += "Not so! ";
return !b;
}
\end{minted}
\end{verbatim}
You know that this is not a pure function, because its memoized version
would fail to produce a log. This function has \newterm{side effects}.
@ -26,28 +25,25 @@ have to pass the log explicitly, in and out. Let's do that by adding a
string argument, and pairing regular output with a string that contains
the updated log:
\begin{minted}{c++}
\begin{verbatim}
pair<bool, string> negate(bool b, string logger) {
return make_pair(!b, logger + "Not so! ");
}
\end{minted}
\end{verbatim}
This function is pure, it has no side effects, it returns the same pair
every time it's called with the same arguments, and it can be memoized
if necessary. However, considering the cumulative nature of the log,
you'd have to memoize all possible histories that can lead to a given
call. There would be a separate memo entry for:
\begin{minted}{c++}
\begin{verbatim}
negate(true, "It was the best of times. ");
\end{minted}
\end{verbatim}
and
\begin{minted}{c++}
\begin{verbatim}
negate(true, "It was the worst of times. ");
\end{minted}
\end{verbatim}
and so on.
It's also not a very good interface for a library function. The callers
@ -64,12 +60,11 @@ continuous log is a separate concern. We still want the function to
produce a string, but we'd like to unburden it from producing a log. So
here's the compromise solution:
\begin{minted}{c++}
\begin{verbatim}
pair<bool, string> negate(bool b) {
return make_pair(!b, "Not so! ");
}
\end{minted}
\end{verbatim}
The idea is that the log will be aggregated \emph{between} function
calls.
@ -77,27 +72,25 @@ To see how this can be done, let's switch to a slightly more realistic
example. We have one function from string to string that turns lower
case characters to upper case:
\begin{minted}{c++}
\begin{verbatim}
string toUpper(string s) {
string result;
int (*toupperp)(int) = &toupper; // toupper is overloaded
transform(begin(s), end(s), back_inserter(result), toupperp);
return result;
}
\end{minted}
\end{verbatim}
and another that splits a string into a vector of strings, breaking it
on whitespace boundaries:
\begin{minted}{c++}
\begin{verbatim}
vector<string> toWords(string s) {
return words(s);
}
\end{minted}
\end{verbatim}
The actual work is done in the auxiliary function \code{words}:
\begin{minted}{c++}
\begin{verbatim}
vector<string> words(string s) {
vector<string> result{""};
for (auto i = begin(s); i != end(s); ++i)
@ -109,11 +102,11 @@ vector<string> words(string s) {
}
return result;
}
\end{minted}
\end{verbatim}
\begin{wrapfigure}{R}{0pt}
\begin{wrapfigure}[11]{R}{0pt}
\raisebox{0pt}[\dimexpr\height-0.75\baselineskip\relax]{
\fbox{\includegraphics[width=1.83333in]{images/piggyback.jpg}}}%
\fbox{\includegraphics[width=1.83333in]{images/piggyback.jpg}}}%
\end{wrapfigure}
We want to modify the functions \code{toUpper} and \code{toWords} so
@ -125,14 +118,13 @@ in a generic way by defining a template \code{Writer} that
encapsulates a pair whose first component is a value of arbitrary type
\code{A} and the second component is a string:
\begin{minted}{c++}
\begin{verbatim}
template<class A>
using Writer = pair<A, string>;
\end{minted}
\end{verbatim}
Here are the embellished functions:
\begin{minted}{c++}
\begin{verbatim}
Writer<string> toUpper(string s) {
string result;
int (*toupperp)(int) = &toupper;
@ -143,20 +135,18 @@ Writer<string> toUpper(string s) {
Writer<vector<string>> toWords(string s) {
return make_pair(words(s), "toWords ");
}
\end{minted}
\end{verbatim}
We want to compose these two functions into another embellished function
that uppercases a string and splits it into words, all the while
producing a log of those actions. Here's how we may do it:
\begin{minted}{c++}
\begin{verbatim}
Writer<vector<string>> process(string s) {
auto p1 = toUpper(s);
auto p2 = toWords(p1.first);
return make_pair(p2.first, p1.second + p2.second);
}
\end{minted}
\end{verbatim}
We have accomplished our goal: The aggregation of the log is no longer
the concern of the individual functions. They produce their own
messages, which are then, externally, concatenated into a larger log.
@ -184,35 +174,32 @@ important point is that this morphism is still considered an arrow
between the objects \code{int} and \code{bool}, even though the
embellished function returns a pair:
\begin{minted}{c++}
\begin{verbatim}
pair<bool, string> isEven(int n) {
return make_pair(n % 2 == 0, "isEven ");
}
\end{minted}
\end{verbatim}
By the laws of a category, we should be able to compose this morphism
with another morphism that goes from the object \code{bool} to
whatever. In particular, we should be able to compose it with our
earlier \code{negate}:
\begin{minted}{c++}
\begin{verbatim}
pair<bool, string> negate(bool b) {
return make_pair(!b, "Not so! ");
}
\end{minted}
\end{verbatim}
Obviously, we cannot compose these two morphisms the same way we compose
regular functions, because of the input/output mismatch. Their
composition should look more like this:
\begin{minted}{c++}
\begin{verbatim}
pair<bool, string> isOdd(int n) {
pair<bool, string> p1 = isEven(n);
pair<bool, string> p2 = negate(p1.first);
return make_pair(p2.first, p1.second + p2.second);
}
\end{minted}
\end{verbatim}
So here's the recipe for the composition of two morphisms in this new
category we are constructing:
@ -237,7 +224,7 @@ corresponding to three objects in our category. It should take two
embellished functions that are composable according to our rules, and
return a third embellished function:
\begin{minted}{c++}
\begin{verbatim}
template<class A, class B, class C>
function<Writer<C>(A)> compose(function<Writer<B>(A)> m1,
function<Writer<C>(B)> m2)
@ -248,23 +235,21 @@ function<Writer<C>(A)> compose(function<Writer<B>(A)> m1,
return make_pair(p2.first, p1.second + p2.second);
};
}
\end{minted}
\end{verbatim}
Now we can go back to our earlier example and implement the composition
of \code{toUpper} and \code{toWords} using this new template:
\begin{minted}{c++}
\begin{minted}[breaklines, breakafter=>>]{text}
Writer<vector<string>> process(string s) {
return compose<string, string, vector<string>>(toUpper, toWords)(s);
}
\end{minted}
There is still a lot of noise with the passing of types to the
\code{compose} template. This can be avoided as long as you have a
C++14-compliant compiler that supports generalized lambda functions with
return type deduction (credit for this code goes to Eric Niebler):
\begin{minted}{c++}
\begin{verbatim}
auto const compose = [](auto m1, auto m2) {
return [m1, m2](auto x) {
auto p1 = m1(x);
@ -272,37 +257,33 @@ auto const compose = [](auto m1, auto m2) {
return make_pair(p2.first, p1.second + p2.second);
};
};
\end{minted}
\end{verbatim}
In this new definition, the implementation of \code{process}
simplifies to:
\begin{minted}{c++}
\begin{verbatim}
Writer<vector<string>> process(string s) {
return compose(toUpper, toWords)(s);
}
\end{minted}
\end{verbatim}
But we are not finished yet. We have defined composition in our new
category, but what are the identity morphisms? These are not our regular
identity functions! They have to be morphisms from type A back to type
A, which means they are embellished functions of the form:
\begin{minted}{c++}
\begin{verbatim}
Writer<A> identity(A);
\end{minted}
\end{verbatim}
They have to behave like units with respect to composition. If you look
at our definition of composition, you'll see that an identity morphism
should pass its argument without change, and only contribute an empty
string to the log:
\begin{minted}{c++}
\begin{verbatim}
template<class A> Writer<A> identity(A x) {
return make_pair(x, "");
}
\end{minted}
\end{verbatim}
You can easily convince yourself that the category we have just defined
is indeed a legitimate category. In particular, our composition is
trivially associative. If you follow what's happening with the first
@ -325,10 +306,9 @@ The same thing in Haskell is a little more terse, and we also get a lot
more help from the compiler. Let's start by defining the \code{Writer}
type:
\begin{minted}{haskell}
\begin{verbatim}
type Writer a = (a, String)
\end{minted}
\end{verbatim}
Here I'm just defining a type alias, an equivalent of a \code{typedef}
(or \code{using}) in C++. The type \code{Writer} is parameterized by
a type variable \code{a} and is equivalent to a pair of \code{a} and
@ -338,17 +318,15 @@ parentheses, separated by a comma.
Our morphisms are functions from an arbitrary type to some
\code{Writer} type:
\begin{minted}{haskell}
\begin{verbatim}
a -> Writer b
\end{minted}
\end{verbatim}
We'll declare the composition as a funny infix operator, sometimes
called the ``fish'':
\begin{minted}{haskell}
\begin{verbatim}
(>=>) :: (a -> Writer b) -> (b -> Writer c) -> (a -> Writer c)
\end{minted}
\end{verbatim}
It's a function of two arguments, each being a function on its own, and
returning a function. The first argument is of the type
\code{(a->Writer b)}, the second is
@ -359,13 +337,12 @@ Here's the definition of this infix operator --- the two arguments
\code{m1} and \code{m2} appearing on either side of the fishy
symbol:
\begin{minted}{haskell}
\begin{verbatim}
m1 >=> m2 = \x ->
let (y, s1) = m1 x
(z, s2) = m2 y
in (z, s1 ++ s2)
\end{minted}
\end{verbatim}
The result is a lambda function of one argument \code{x}. The lambda
is written as a backslash --- think of it as the Greek letter λ with an
amputated leg.
@ -389,24 +366,22 @@ I will also define the identity morphism for our category, but for
reasons that will become clear much later, I will call it
\code{return}.
\begin{minted}{haskell}
\begin{verbatim}
return :: a -> Writer a
return x = (x, "")
\end{minted}
\end{verbatim}
For completeness, let's have the Haskell versions of the embellished
functions \code{upCase} and \code{toWords}:
\begin{minted}{haskell}
\begin{verbatim}
upCase :: String -> Writer String
upCase s = (map toUpper s, "upCase ")
\end{minted}
\end{verbatim}
\begin{minted}{haskell}
\begin{verbatim}
toWords :: String -> Writer [String]
toWords s = (words s, "toWords ")
\end{minted}
\end{verbatim}
The function \code{map} corresponds to the C++ \code{transform}. It
applies the character function \code{toUpper} to the string
\code{s}. The auxiliary function \code{words} is defined in the
@ -415,10 +390,10 @@ standard Prelude library.
Finally, the composition of the two functions is accomplished with the
help of the fish operator:
\begin{minted}{haskell}
\begin{verbatim}
process :: String -> Writer [String]
process = upCase >=> toWords
\end{minted}
\end{verbatim}
\section{Kleisli Categories}\label{kleisli-categories}
@ -457,7 +432,7 @@ mathematical sense, so it doesn't fit the standard categorical mold. It
can, however, be represented by a function that returns an embellished
type \code{optional}:
\begin{minted}{c++}
\begin{verbatim}
template<class A> class optional {
bool _isValid;
A _value;
@ -467,18 +442,16 @@ public:
bool isValid() const { return _isValid; }
A value() const { return _value; }
};
\end{minted}
\end{verbatim}
As an example, here's the implementation of the embellished function
\code{safe\_root}:
\begin{minted}{c++}
\begin{verbatim}
optional<double> safe_root(double x) {
if (x >= 0) return optional<double>{sqrt(x)};
else return optional<double>{};
}
\end{minted}
\end{verbatim}
Here's the challenge:
\begin{enumerate}