mirror of
https://github.com/hmemcpy/milewski-ctfp-pdf.git
synced 2024-11-26 12:44:57 +03:00
C++ code fixes
This commit is contained in:
parent
6e27058441
commit
d5666cd5e4
Binary file not shown.
@ -50,7 +50,7 @@ C g(B b);
|
||||
\end{Verbatim}
|
||||
Their composition is:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
C g_after_f(A a)
|
||||
{
|
||||
return g(f(a));
|
||||
@ -87,9 +87,9 @@ g ◦ f
|
||||
\end{Verbatim}
|
||||
You can even use Unicode double colons and arrows:
|
||||
|
||||
\begin{minted}[escapeinside=||,mathescape=true]{text}
|
||||
f |\ensuremath{\Colon}| A → B
|
||||
\end{minted}
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
f \ensuremath{\Colon} A → B
|
||||
\end{Verbatim}
|
||||
So here's the first Haskell lesson: Double colon means ``has the type
|
||||
of\ldots{}'' A function type is created by inserting an arrow between
|
||||
two types. You compose two functions by inserting a period between them
|
||||
@ -142,7 +142,7 @@ identity function that just returns back its argument. The
|
||||
implementation is the same for every type, which means this function is
|
||||
universally polymorphic. In C++ we could define it as a template:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class T> T id(T x) { return x; }
|
||||
\end{Verbatim}
|
||||
Of course, in C++ nothing is that simple, because you have to take into
|
||||
|
@ -169,7 +169,7 @@ 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:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A> G<A> alpha(F<A>);
|
||||
\end{Verbatim}
|
||||
There is a more profound difference between Haskell's polymorphic
|
||||
@ -746,7 +746,7 @@ for vertical composition, but not vice versa.
|
||||
Finally, the two compositions satisfy the interchange law:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
(β' ⋅ α') ◦ (β ⋅ α) = (β' ◦ β) ⋅ (α' ◦ α)
|
||||
(β' \ensuremath{\cdot} α') ◦ (β \ensuremath{\cdot} α) = (β' ◦ β) \ensuremath{\cdot} (α' ◦ α)
|
||||
\end{Verbatim}
|
||||
|
||||
I will quote Saunders Mac Lane here: The reader may enjoy writing down
|
||||
|
@ -247,7 +247,7 @@ The function \code{product} multiplies all elements of a list. That's
|
||||
just like a definition of factorial taken from a math text. Compare this
|
||||
with C:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
int fact(int n) {
|
||||
int i;
|
||||
int result = 1;
|
||||
@ -342,7 +342,7 @@ Think of functions from and to this type. A function from \code{void}
|
||||
can always be called. If it's a pure function, it will always return the
|
||||
same result. Here's an example of such a function:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
int f44() { return 44; }
|
||||
\end{Verbatim}
|
||||
You might think of this function as taking ``nothing'', but as we've
|
||||
@ -418,7 +418,7 @@ unit _ = ()
|
||||
\end{Verbatim}
|
||||
In C++ you would write this function as:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class T>
|
||||
void unit(T) {}
|
||||
\end{Verbatim}
|
||||
@ -434,7 +434,7 @@ data Bool = True | False
|
||||
\code{True} or \code{False}.) In principle, one should also be able
|
||||
to define a Boolean type in C++ as an enumeration:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
enum bool {
|
||||
true,
|
||||
false
|
||||
@ -455,8 +455,8 @@ the Haskell library \code{Data.Char} is full of predicates like
|
||||
\code{} that defines, among others, \code{isalpha} and
|
||||
\code{isdigit}, but these return an \code{int} rather than a
|
||||
Boolean. The actual predicates are defined in \code{std::ctype} and
|
||||
have the form \code{ctype::is(alpha,\ c)},
|
||||
\code{ctype::is(digit,\ c)}, etc.
|
||||
have the form \code{ctype::is(alpha, c)},
|
||||
\code{ctype::is(digit, c)}, etc.
|
||||
|
||||
\section{Challenges}\label{challenges}
|
||||
|
||||
@ -491,18 +491,18 @@ have the form \code{ctype::is(alpha,\ c)},
|
||||
\item
|
||||
The factorial function from the example in the text.
|
||||
\item
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
std::getchar()
|
||||
\end{Verbatim}
|
||||
\item
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
bool f() {
|
||||
std::cout << "Hello!" << std::endl;
|
||||
return true;
|
||||
}
|
||||
\end{Verbatim}
|
||||
\item
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
int f(int x)
|
||||
{
|
||||
static int y = 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
\lettrine[lhang=0.17]{Y}{ou can get real appreciation} for categories by studying a variety of
|
||||
\lettrine[lhang=0.17]{Y}{ou can get} real appreciation for categories by studying a variety of
|
||||
examples. Categories come in all shapes and sizes and often pop up in
|
||||
unexpected places. We'll start with something really simple.
|
||||
|
||||
@ -195,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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class T>
|
||||
T mempty = delete;
|
||||
|
||||
@ -223,7 +223,7 @@ 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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<>
|
||||
std::string mempty<std::string> = {""};
|
||||
|
||||
|
@ -5,7 +5,7 @@ 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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
string logger;
|
||||
|
||||
bool negate(bool b) {
|
||||
@ -25,7 +25,7 @@ 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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
pair<bool, string> negate(bool b, string logger) {
|
||||
return make_pair(!b, logger + "Not so! ");
|
||||
}
|
||||
@ -60,7 +60,7 @@ 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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
pair<bool, string> negate(bool b) {
|
||||
return make_pair(!b, "Not so! ");
|
||||
}
|
||||
@ -72,7 +72,7 @@ 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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
string toUpper(string s) {
|
||||
string result;
|
||||
int (*toupperp)(int) = &toupper; // toupper is overloaded
|
||||
@ -83,14 +83,14 @@ string toUpper(string s) {
|
||||
and another that splits a string into a vector of strings, breaking it
|
||||
on whitespace boundaries:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
vector<string> toWords(string s) {
|
||||
return words(s);
|
||||
}
|
||||
\end{Verbatim}
|
||||
The actual work is done in the auxiliary function \code{words}:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
vector<string> words(string s) {
|
||||
vector<string> result{""};
|
||||
for (auto i = begin(s); i != end(s); ++i)
|
||||
@ -118,13 +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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A>
|
||||
using Writer = pair<A, string>;
|
||||
\end{Verbatim}
|
||||
Here are the embellished functions:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
Writer<string> toUpper(string s) {
|
||||
string result;
|
||||
int (*toupperp)(int) = &toupper;
|
||||
@ -140,7 +140,7 @@ 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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
Writer<vector<string>> process(string s) {
|
||||
auto p1 = toUpper(s);
|
||||
auto p2 = toWords(p1.first);
|
||||
@ -174,7 +174,7 @@ 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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
pair<bool, string> isEven(int n) {
|
||||
return make_pair(n % 2 == 0, "isEven ");
|
||||
}
|
||||
@ -184,7 +184,7 @@ 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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
pair<bool, string> negate(bool b) {
|
||||
return make_pair(!b, "Not so! ");
|
||||
}
|
||||
@ -193,7 +193,7 @@ 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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
pair<bool, string> isOdd(int n) {
|
||||
pair<bool, string> p1 = isEven(n);
|
||||
pair<bool, string> p2 = negate(p1.first);
|
||||
@ -224,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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A, class B, class C>
|
||||
function<Writer<C>(A)> compose(function<Writer<B>(A)> m1,
|
||||
function<Writer<C>(B)> m2)
|
||||
@ -249,7 +249,7 @@ There is still a lot of noise with the passing of types to the
|
||||
C++14-compliant compiler that supports generalized lambda functions with
|
||||
return type deduction (credit for this code goes to Eric Niebler):
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
auto const compose = [](auto m1, auto m2) {
|
||||
return [m1, m2](auto x) {
|
||||
auto p1 = m1(x);
|
||||
@ -261,7 +261,7 @@ auto const compose = [](auto m1, auto m2) {
|
||||
In this new definition, the implementation of \code{process}
|
||||
simplifies to:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
Writer<vector<string>> process(string s) {
|
||||
return compose(toUpper, toWords)(s);
|
||||
}
|
||||
@ -271,7 +271,7 @@ 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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
Writer<A> identity(A);
|
||||
\end{Verbatim}
|
||||
They have to behave like units with respect to composition. If you look
|
||||
@ -279,7 +279,7 @@ 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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A> Writer<A> identity(A x) {
|
||||
return make_pair(x, "");
|
||||
}
|
||||
@ -324,7 +324,7 @@ a -> Writer b
|
||||
We'll declare the composition as a funny infix operator, sometimes
|
||||
called the ``fish'':
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
(>=>) :: (a -> Writer b) -> (b -> Writer c) -> (a -> Writer c)
|
||||
\end{Verbatim}
|
||||
It's a function of two arguments, each being a function on its own, and
|
||||
@ -390,7 +390,7 @@ standard Prelude library.
|
||||
Finally, the composition of the two functions is accomplished with the
|
||||
help of the fish operator:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
process :: String -> Writer [String]
|
||||
process = upCase >=> toWords
|
||||
\end{Verbatim}
|
||||
@ -432,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{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A> class optional {
|
||||
bool _isValid;
|
||||
A _value;
|
||||
@ -446,7 +446,7 @@ public:
|
||||
As an example, here's the implementation of the embellished function
|
||||
\code{safe\_root}:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
optional<double> safe_root(double x) {
|
||||
if (x >= 0) return optional<double>{sqrt(x)};
|
||||
else return optional<double>{};
|
||||
|
@ -265,7 +265,7 @@ snd (_, y) = y
|
||||
\end{Verbatim}
|
||||
In C++, we would use template functions, for instance:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A, class B> A
|
||||
fst(pair<A, B> const & p) {
|
||||
return p.first;
|
||||
@ -359,7 +359,7 @@ equations are in natural numbers, and the dot is multiplication:
|
||||
\emph{m} is a common factor shared by \emph{p'} and \emph{q'}.
|
||||
|
||||
Just to build some intuitions, let me show you that the pair
|
||||
\code{(Int,\ Bool)} with the two canonical projections, \code{fst}
|
||||
\code{(Int, Bool)} with the two canonical projections, \code{fst}
|
||||
and \code{snd} is indeed \emph{better} than the two candidates I
|
||||
presented before.
|
||||
|
||||
@ -387,7 +387,7 @@ The \code{m} for the second example is similarly uniquely determined:
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
m (x, _, b) = (x, b)
|
||||
\end{Verbatim}
|
||||
We were able to show that \code{(Int,\ Bool)} is better than either of
|
||||
We were able to show that \code{(Int, Bool)} is better than either of
|
||||
the two candidates. Let's see why the opposite is not true. Could we
|
||||
find some \code{m'} that would help us reconstruct \code{fst}
|
||||
and \code{snd} from \code{p} and \code{q}?
|
||||
@ -512,7 +512,7 @@ have to define a tag --- an enumeration --- and combine it with the
|
||||
union. For instance, a tagged union of an \code{int} and a\\
|
||||
\code{char const *} could be implemented as:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
struct Contact {
|
||||
enum { isPhone, isEmail } tag;
|
||||
union { int phoneNum; char const * emailAddr; };
|
||||
@ -522,7 +522,7 @@ The two injections can either be implemented as constructors or as
|
||||
functions. For instance, here's the first injection as a function
|
||||
\code{PhoneNum}:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
Contact PhoneNum(int n) {
|
||||
Contact c;
|
||||
c.tag = isPhone;
|
||||
@ -673,7 +673,7 @@ isomorphism is the same as a bijection.
|
||||
\section{Challenges}\label{challenges}
|
||||
|
||||
\begin{enumerate}
|
||||
\tightlist
|
||||
\tightlist
|
||||
\item
|
||||
Show that the terminal object is unique up to unique isomorphism.
|
||||
\item
|
||||
@ -688,14 +688,14 @@ isomorphism is the same as a bijection.
|
||||
Show that \code{Either} is a ``better'' coproduct than \code{int}
|
||||
equipped with two injections:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
int i(int n) { return n; }
|
||||
int j(bool b) { return b? 0: 1; }
|
||||
\end{Verbatim}
|
||||
|
||||
Hint: Define a function
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
int m(Either const & e);
|
||||
\end{Verbatim}
|
||||
|
||||
@ -707,7 +707,7 @@ int m(Either const & e);
|
||||
\item
|
||||
Still continuing: What about these injections?
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
int i(int n) {
|
||||
if (n < 0) return n;
|
||||
return n + 2;
|
||||
|
@ -25,8 +25,8 @@ Library.
|
||||
\end{figure}
|
||||
|
||||
\noindent
|
||||
Pairs are not strictly commutative: a pair \code{(Int,\ Bool)} cannot
|
||||
be substituted for a pair \code{(Bool,\ Int)}, even though they carry
|
||||
Pairs are not strictly commutative: a pair \code{(Int, Bool)} cannot
|
||||
be substituted for a pair \code{(Bool, Int)}, even though they carry
|
||||
the same information. They are, however, commutative up to isomorphism
|
||||
--- the isomorphism being given by the \code{swap} function (which is
|
||||
its own inverse):
|
||||
@ -114,7 +114,7 @@ can be defined alternatively as:
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
data Pair a b = P a b
|
||||
\end{Verbatim}
|
||||
Here, \code{Pair\ a\ b} is the name of the type paremeterized by two
|
||||
Here, \code{Pair a b} is the name of the type paremeterized by two
|
||||
other types, \code{a} and \code{b}; and \code{P} is the name of
|
||||
the data constructor. You define a pair type by passing two types to the
|
||||
\code{Pair} type constructor. You construct a pair value by passing
|
||||
@ -173,7 +173,7 @@ named fields is called a record in Haskell, and a \code{struct} in C.
|
||||
Let's have a look at a simple example. We want to describe chemical
|
||||
elements by combining two strings, name and symbol; and an integer, the
|
||||
atomic number; into one data structure. We can use a tuple
|
||||
\code{(String,\ String,\ Int)} and remember which component represents
|
||||
\code{(String, String, Int)} and remember which component represents
|
||||
what. We would extract components by pattern matching, as in this
|
||||
function that checks if the symbol of the element is the prefix of its
|
||||
name (as in \textbf{He} being the prefix of \textbf{Helium}):
|
||||
@ -185,7 +185,7 @@ startsWithSymbol (name, symbol, _) = isPrefixOf symbol name
|
||||
This code is error prone, and is hard to read and maintain. It's much
|
||||
better to define a record:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
data Element = Element { name :: String
|
||||
, symbol :: String
|
||||
, atomicNumber :: Int }
|
||||
@ -193,7 +193,7 @@ data Element = Element { name :: String
|
||||
The two representations are isomorphic, as witnessed by these two
|
||||
conversion functions, which are the inverse of each other:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
tupleToElem :: (String, String, Int) -> Element
|
||||
tupleToElem (n, s, a) = Element { name = n
|
||||
, symbol = s
|
||||
@ -242,7 +242,7 @@ And like pairs, \code{Either}s are commutative (up to isomorphism),
|
||||
can be nested, and the nesting order is irrelevant (up to isomorphism).
|
||||
So we can, for instance, define a sum equivalent of a triple:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
data OneOfThree a b c = Sinistral a | Medial b | Dextral c
|
||||
\end{Verbatim}
|
||||
and so on.
|
||||
@ -279,7 +279,7 @@ data Color = Red | Green | Blue
|
||||
\end{Verbatim}
|
||||
is the C++:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
enum { Red, Green, Blue };
|
||||
\end{Verbatim}
|
||||
An even simpler sum type:
|
||||
@ -328,7 +328,7 @@ List a = Nil | Cons a (List a)
|
||||
can be translated to C++ using the null pointer trick to implement the
|
||||
empty list:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A>
|
||||
class List {
|
||||
Node<A> * _head;
|
||||
@ -380,7 +380,7 @@ the first constructor argument with a wildcard, because we are not
|
||||
interested in it. The second argument to \code{Cons} is bound to the
|
||||
variable \code{t} (I will call these things variables even though,
|
||||
strictly speaking, they never vary: once bound to an expression, a
|
||||
variable never changes). The return value is \code{Just\ t}. Now,
|
||||
variable never changes). The return value is \code{Just t}. Now,
|
||||
depending on how your \code{List} was created, it will match one of
|
||||
the clauses. If it was created using \code{Cons}, the two arguments
|
||||
that were passed to it will be retrieved (and the first discarded).
|
||||
@ -417,7 +417,7 @@ example, is it possible to create a pair of, say \code{Int} and
|
||||
|
||||
To create a pair you need two values. Although you can easily come up
|
||||
with an integer, there is no value of type \code{Void}. Therefore, for
|
||||
any type \code{a}, the type \code{(a,\ Void)} is uninhabited --- has
|
||||
any type \code{a}, the type \code{(a, Void)} is uninhabited --- has
|
||||
no values --- and is therefore equivalent to \code{Void}. In other
|
||||
words, \code{a*0 = 0}.
|
||||
|
||||
@ -511,7 +511,7 @@ equation:
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
List a = Nil | Cons a (List a)
|
||||
\end{Verbatim}
|
||||
If we do our usual substitutions, and also replace \code{List\ a} with
|
||||
If we do our usual substitutions, and also replace \code{List a} with
|
||||
\code{x}, we get the equation:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
@ -613,7 +613,7 @@ circ (Rect d h) = 2.0 * (d + h)
|
||||
have to touch in Haskell vs. C++ or Java? (Even if you're not a
|
||||
Haskell programmer, the modifications should be pretty obvious.)
|
||||
\item
|
||||
Show that \code{a\ +\ a\ =\ 2\ *\ a} holds for types (up to
|
||||
Show that \code{a + a = 2 * a} holds for types (up to
|
||||
isomorphism). Remember that \code{2} corresponds to \code{Bool},
|
||||
according to our translation table.
|
||||
\end{enumerate}
|
@ -56,7 +56,7 @@ want all identity morphisms in C to be mapped to identity morphisms in
|
||||
D:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
F ida = idF a
|
||||
F id\textsubscript{a} = id\textsubscript{F a}
|
||||
\end{Verbatim}
|
||||
Here, \emph{id\textsubscript{a}} is the identity at the object \emph{a},
|
||||
and \emph{id\textsubscript{F a}} the identity at \emph{F a}.
|
||||
@ -209,7 +209,7 @@ There are two cases to consider: \code{Nothing} and \code{Just}.
|
||||
Here's the first case (I'm using Haskell pseudo-code to transform the
|
||||
left hand side to the right hand side):
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
fmap id Nothing
|
||||
= { definition of fmap }
|
||||
Nothing
|
||||
@ -223,7 +223,7 @@ backwards. I replaced the expression \code{Nothing} with
|
||||
in the middle --- here it was \code{Nothing}. The second case is also
|
||||
easy:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
fmap id (Just x)
|
||||
= { definition of fmap }
|
||||
Just (id x)
|
||||
@ -239,7 +239,7 @@ fmap (g . f) = fmap g . fmap f
|
||||
\end{Verbatim}
|
||||
First the \code{Nothing} case:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
fmap (g . f) Nothing
|
||||
= { definition of fmap }
|
||||
Nothing
|
||||
@ -250,7 +250,7 @@ First the \code{Nothing} case:
|
||||
\end{Verbatim}
|
||||
And then the \code{Just} case:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
fmap (g . f) (Just x)
|
||||
= { definition of fmap }
|
||||
Just ((g . f) x)
|
||||
@ -266,7 +266,7 @@ And then the \code{Just} case:
|
||||
It's worth stressing that equational reasoning doesn't work for C++
|
||||
style ``functions'' with side effects. Consider this code:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
int square(int x) {
|
||||
return x * x;
|
||||
}
|
||||
@ -281,7 +281,7 @@ double y = square(counter());
|
||||
Using equational reasoning, you would be able to inline \code{square}
|
||||
to get:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
double y = counter() * counter();
|
||||
\end{Verbatim}
|
||||
This is definitely not a valid transformation, and it will not produce
|
||||
@ -299,7 +299,7 @@ implementation is much more complex, dealing with various ways the
|
||||
argument may be passed, with copy semantics, and with the resource
|
||||
management issues characteristic of C++):
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class T>
|
||||
class optional {
|
||||
bool _isValid; // the tag
|
||||
@ -315,7 +315,7 @@ mapping of types. It maps any type \code{T} to a new type
|
||||
\code{optional<T>}. Let's define its action on
|
||||
functions:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A, class B>
|
||||
std::function<optional<B>(optional<A>)>
|
||||
fmap(std::function<B(A)> f) {
|
||||
@ -330,7 +330,7 @@ fmap(std::function<B(A)> f) {
|
||||
This is a higher order function, taking a function as an argument and
|
||||
returning a function. Here's the uncurried version of it:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A, class B>
|
||||
optional<B> fmap(std::function<B(A)> f, optional<A> opt) {
|
||||
if (!opt.isValid())
|
||||
@ -428,7 +428,7 @@ template class, like \code{optional}, so by analogy, we would
|
||||
parameterize \code{fmap} with a \newterm{template template parameter}
|
||||
\code{F}. This is the syntax for it:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<template<class> F, class A, class B>
|
||||
F<B> fmap(std::function<B(A)>, F<A>);
|
||||
\end{Verbatim}
|
||||
@ -436,14 +436,14 @@ We would like to be able to specialize this template for different
|
||||
functors. Unfortunately, there is a prohibition against partial
|
||||
specialization of template functions in C++. You can't write:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A, class B>
|
||||
optional<B> fmap<optional>(std::function<B(A)> f, optional<A> opt)
|
||||
\end{Verbatim}
|
||||
Instead, we have to fall back on function overloading, which brings us
|
||||
back to the original definition of the uncurried \code{fmap}:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A, class B>
|
||||
optional<B> fmap(std::function<B(A)> f, optional<A> opt) {
|
||||
if (!opt.isValid())
|
||||
@ -514,7 +514,7 @@ If you are more comfortable with C++, consider the case of a
|
||||
container. The implementation of \code{fmap} for \code{std::vector}
|
||||
is just a thin encapsulation of \code{std::transform}:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A, class B>
|
||||
std::vector<B> fmap(std::function<B(A)> f, std::vector<A> v) {
|
||||
std::vector<B> w;
|
||||
@ -528,7 +528,7 @@ std::vector<B> fmap(std::function<B(A)> f, std::vector<A> v) {
|
||||
We can use it, for instance, to square the elements of a sequence of
|
||||
numbers:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
std::vector<int> v{ 1, 2, 3, 4 };
|
||||
auto w = fmap([](int i) { return i*i; }, v);
|
||||
std::copy( std::begin(w)
|
||||
@ -691,7 +691,7 @@ This might be a little clearer in C++ (I never thought I would utter
|
||||
those words!), where there is a stronger distinction between type
|
||||
arguments --- which are compile-time --- and values, which are run-time:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class C, class A>
|
||||
struct Const {
|
||||
Const(C v) : _v(v) {}
|
||||
@ -702,7 +702,7 @@ The C++ implementation of \code{fmap} also ignores the function
|
||||
argument and essentially re-casts the \code{Const} argument without
|
||||
changing its value:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class C, class A, class B>
|
||||
Const<C, B> fmap(std::function<B(A)> f, Const<C, A> c) {
|
||||
return Const<C, B>{c._v};
|
||||
|
@ -249,7 +249,7 @@ arguments. The syntax is the same.
|
||||
If you're getting a little lost, try applying \code{BiComp} to
|
||||
\code{Either}, \code{Const ()}, \code{Identity}, \code{a}, and
|
||||
\code{b}, in this order. You will recover our bare-bone version of
|
||||
\code{Maybe\ b} (\code{a} is ignored).
|
||||
\code{Maybe b} (\code{a} is ignored).
|
||||
|
||||
The new data type \code{BiComp} is a bifunctor in \code{a} and
|
||||
\code{b}, but only if \code{bf} is itself a \code{Bifunctor} and
|
||||
@ -260,11 +260,11 @@ know that there will be a definition of \code{bimap} available for
|
||||
instance declaration: a set of class constraints followed by a double
|
||||
arrow:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{minted}[breaklines]{text}
|
||||
instance (Bifunctor bf, Functor fu, Functor gu) =>
|
||||
Bifunctor (BiComp bf fu gu) where
|
||||
bimap f1 f2 (BiComp x) = BiComp ((bimap (fmap f1) (fmap f2)) x)
|
||||
\end{Verbatim}
|
||||
\end{minted}
|
||||
The implementation of \code{bimap} for \code{BiComp} is given in
|
||||
terms of \code{bimap} for \code{bf} and the two \code{fmap}s for
|
||||
\code{fu} and \code{gu}. The compiler automatically infers all the
|
||||
@ -305,9 +305,9 @@ can't it be automated and performed by the compiler? Indeed, it can, and
|
||||
it is. You need to enable a particular Haskell extension by including
|
||||
this line at the top of your source file:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{minted}{haskell}
|
||||
{-# LANGUAGE DeriveFunctor #-}
|
||||
\end{Verbatim}
|
||||
\end{minted}
|
||||
and then add \code{deriving Functor} to your data structure:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
@ -334,7 +334,7 @@ is made into a generic template, you should be able to quickly implement
|
||||
Let's have a look at a tree data structure, which we would define in
|
||||
Haskell as a recursive sum type:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
data Tree a = Leaf a | Node (Tree a) (Tree a)
|
||||
deriving Functor
|
||||
\end{Verbatim}
|
||||
@ -353,7 +353,7 @@ The base class must define at least one virtual function in order to
|
||||
support dynamic casting, so we'll make the destructor virtual (which is
|
||||
a good idea in any case):
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class T>
|
||||
struct Tree {
|
||||
virtual ~Tree() {};
|
||||
@ -361,7 +361,7 @@ struct Tree {
|
||||
\end{Verbatim}
|
||||
The \code{Leaf} is just an \code{Identity} functor in disguise:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class T>
|
||||
struct Leaf : public Tree<T> {
|
||||
T _label;
|
||||
@ -370,7 +370,7 @@ struct Leaf : public Tree<T> {
|
||||
\end{Verbatim}
|
||||
The \code{Node} is a product type:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class T>
|
||||
struct Node : public Tree<T> {
|
||||
Tree<T> * _left;
|
||||
@ -386,7 +386,7 @@ is treated like a bifunctor composed with two copies of the
|
||||
analyzing code in these terms, but it's a good exercise in categorical
|
||||
thinking.
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
template<class A, class B>
|
||||
Tree<B> * fmap(std::function<B(A)> f, Tree<A> * t) {
|
||||
Leaf<A> * pl = dynamic_cast <Leaf<A>*>(t);
|
||||
@ -405,7 +405,7 @@ issues, but in production code you would probably use smart pointers
|
||||
|
||||
Compare it with the Haskell implementation of \code{fmap}:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
instance Functor Tree where
|
||||
fmap f (Leaf a) = Leaf (f a)
|
||||
fmap f (Node t t') = Node (fmap f t) (fmap f t')
|
||||
@ -467,7 +467,7 @@ So \code{id} will take \code{Writer a} and turn it into
|
||||
\code{Writer a}. The fish operator will fish out the value of
|
||||
\code{a} and pass it as \code{x} to the lambda. There, \code{f}
|
||||
will turn it into a \code{b} and \code{return} will embellish it,
|
||||
making it \code{Writer\ b}. Putting it all together, we end up with a
|
||||
making it \code{Writer b}. Putting it all together, we end up with a
|
||||
function that takes \code{Writer a} and returns \code{Writer b},
|
||||
exactly what \code{fmap} is supposed to produce.
|
||||
|
||||
@ -479,7 +479,7 @@ every functor, though, gives rise to a Kleisli category.)
|
||||
|
||||
You might wonder if the \code{fmap} we have just defined is the same
|
||||
\code{fmap} the compiler would have derived for us with
|
||||
\code{deriving\ Functor}. Interestingly enough, it is. This is due to
|
||||
\code{deriving Functor}. Interestingly enough, it is. This is due to
|
||||
the way Haskell implements polymorphic functions. It's called
|
||||
\newterm{parametric polymorphism}, and it's a source of so called
|
||||
\newterm{theorems for free}. One of those theorems says that, if there is
|
||||
@ -577,13 +577,13 @@ by the way --- the kind we've been studying thus far --- are called
|
||||
Here's the typeclass defining a contravariant functor (really, a
|
||||
contravariant \emph{endo}functor) in Haskell:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
class Contravariant f where
|
||||
contramap :: (b -> a) -> (f a -> f b)
|
||||
\end{Verbatim}
|
||||
Our type constructor \code{Op} is an instance of it:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
instance Contravariant (Op r) where
|
||||
-- (b -> a) -> Op r a -> Op r b
|
||||
contramap f g = g . f
|
||||
@ -623,7 +623,7 @@ which is contra-functorial in the first argument and functorial in the
|
||||
second. Here's the appropriate typeclass taken from the
|
||||
\code{Data.Profunctor} library:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
class Profunctor p where
|
||||
dimap :: (a -> b) -> (c -> d) -> p b c -> p a d
|
||||
dimap f g = lmap f . rmap g
|
||||
@ -649,7 +649,7 @@ the defaults for \code{lmap} and \code{rmap}, or implementing both
|
||||
Now we can assert that the function-arrow operator is an instance of a
|
||||
\code{Profunctor}:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
instance Profunctor (->) where
|
||||
dimap ab cd bc = cd . bc . ab
|
||||
lmap = flip (.)
|
||||
@ -677,7 +677,7 @@ data Pair a b = Pair a b
|
||||
Show the isomorphism between the standard definition of \code{Maybe}
|
||||
and this desugaring:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
type Maybe' a = Either (Const () a) (Identity a)
|
||||
\end{Verbatim}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
\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}
|
||||
\begin{wrapfigure}[12]{R}{0pt}
|
||||
\raisebox{0pt}[\dimexpr\height-0.75\baselineskip\relax]{
|
||||
\fbox{\includegraphics[width=40mm]{images/set-hom-set.jpg}}}%
|
||||
\caption{Hom-set in Set is just a set}
|
||||
@ -322,14 +322,14 @@ initializer lists).
|
||||
You can partially apply a C++ function using the template
|
||||
\code{std::bind}. For instance, given a function of two strings:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
std::string catstr(std::string s1, std::string s2) {
|
||||
return s1 + s2;
|
||||
}
|
||||
\end{Verbatim}
|
||||
you can define a function of one string:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
using namespace std::placeholders;
|
||||
|
||||
auto greet = std::bind(catstr, "Hello ", _1);
|
||||
@ -339,7 +339,7 @@ Scala, which is more functional than C++ or Java, falls somewhere in
|
||||
between. If you anticipate that the function you're defining will be
|
||||
partially applied, you define it with multiple argument lists:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
def catstr(s1: String)(s2: String) = s1 + s2
|
||||
\end{Verbatim}
|
||||
Of course that requires some amount of foresight or prescience on the
|
||||
|
@ -52,7 +52,7 @@ directly from function to function. We also inline short segments of
|
||||
glue code rather than abstract them into helper functions. Here's an
|
||||
imperative-style implementation of the vector-length function in C:
|
||||
|
||||
\begin{Verbatim}[commandchars=\\\{\}]
|
||||
\begin{Verbatim}
|
||||
double vlen(double * v) {
|
||||
double d = 0.0;
|
||||
int n;
|
||||
|
Loading…
Reference in New Issue
Block a user