diff --git a/ctfp.pdf b/ctfp.pdf index f926dda..393bbc6 100644 Binary files a/ctfp.pdf and b/ctfp.pdf differ diff --git a/src/content/1.3/Categories Great and Small.tex b/src/content/1.3/Categories Great and Small.tex index d390a1d..f328fa9 100644 --- a/src/content/1.3/Categories Great and Small.tex +++ b/src/content/1.3/Categories Great and Small.tex @@ -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 T mempty = delete; @@ -216,9 +207,7 @@ template { mempty } -> 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 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: diff --git a/src/content/1.4/Kleisli Categories.tex b/src/content/1.4/Kleisli Categories.tex index e5bc4f7..dd562fe 100644 --- a/src/content/1.4/Kleisli Categories.tex +++ b/src/content/1.4/Kleisli Categories.tex @@ -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 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 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 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 words(string s) { vector result{""}; for (auto i = begin(s); i != end(s); ++i) @@ -109,11 +102,11 @@ vector 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 using Writer = pair; -\end{minted} - +\end{verbatim} Here are the embellished functions: -\begin{minted}{c++} +\begin{verbatim} Writer toUpper(string s) { string result; int (*toupperp)(int) = &toupper; @@ -143,20 +135,18 @@ Writer toUpper(string s) { Writer> 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> 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 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 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 isOdd(int n) { pair p1 = isEven(n); pair 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 function(A)> compose(function(A)> m1, function(B)> m2) @@ -248,23 +235,21 @@ function(A)> compose(function(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> process(string s) { return compose>(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> 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 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 Writer 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 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 safe_root(double x) { if (x >= 0) return optional{sqrt(x)}; else return optional{}; } -\end{minted} - +\end{verbatim} Here's the challenge: \begin{enumerate}