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}
|
\end{Verbatim}
|
||||||
Their composition is:
|
Their composition is:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
C g_after_f(A a)
|
C g_after_f(A a)
|
||||||
{
|
{
|
||||||
return g(f(a));
|
return g(f(a));
|
||||||
@ -87,9 +87,9 @@ g ◦ f
|
|||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
You can even use Unicode double colons and arrows:
|
You can even use Unicode double colons and arrows:
|
||||||
|
|
||||||
\begin{minted}[escapeinside=||,mathescape=true]{text}
|
\begin{Verbatim}[commandchars=\\\{\}]
|
||||||
f |\ensuremath{\Colon}| A → B
|
f \ensuremath{\Colon} A → B
|
||||||
\end{minted}
|
\end{Verbatim}
|
||||||
So here's the first Haskell lesson: Double colon means ``has the type
|
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
|
of\ldots{}'' A function type is created by inserting an arrow between
|
||||||
two types. You compose two functions by inserting a period between them
|
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
|
implementation is the same for every type, which means this function is
|
||||||
universally polymorphic. In C++ we could define it as a template:
|
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; }
|
template<class T> T id(T x) { return x; }
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
Of course, in C++ nothing is that simple, because you have to take into
|
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
|
\code{a}. This is another example of the terseness of the Haskell
|
||||||
syntax. A similar construct in C++ would be slightly more verbose:
|
syntax. A similar construct in C++ would be slightly more verbose:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A> G<A> alpha(F<A>);
|
template<class A> G<A> alpha(F<A>);
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
There is a more profound difference between Haskell's polymorphic
|
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:
|
Finally, the two compositions satisfy the interchange law:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}[commandchars=\\\{\}]
|
||||||
(β' ⋅ α') ◦ (β ⋅ α) = (β' ◦ β) ⋅ (α' ◦ α)
|
(β' \ensuremath{\cdot} α') ◦ (β \ensuremath{\cdot} α) = (β' ◦ β) \ensuremath{\cdot} (α' ◦ α)
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
|
|
||||||
I will quote Saunders Mac Lane here: The reader may enjoy writing down
|
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
|
just like a definition of factorial taken from a math text. Compare this
|
||||||
with C:
|
with C:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
int fact(int n) {
|
int fact(int n) {
|
||||||
int i;
|
int i;
|
||||||
int result = 1;
|
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
|
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:
|
same result. Here's an example of such a function:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
int f44() { return 44; }
|
int f44() { return 44; }
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
You might think of this function as taking ``nothing'', but as we've
|
You might think of this function as taking ``nothing'', but as we've
|
||||||
@ -418,7 +418,7 @@ unit _ = ()
|
|||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
In C++ you would write this function as:
|
In C++ you would write this function as:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class T>
|
template<class T>
|
||||||
void unit(T) {}
|
void unit(T) {}
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
@ -434,7 +434,7 @@ data Bool = True | False
|
|||||||
\code{True} or \code{False}.) In principle, one should also be able
|
\code{True} or \code{False}.) In principle, one should also be able
|
||||||
to define a Boolean type in C++ as an enumeration:
|
to define a Boolean type in C++ as an enumeration:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
enum bool {
|
enum bool {
|
||||||
true,
|
true,
|
||||||
false
|
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{} that defines, among others, \code{isalpha} and
|
||||||
\code{isdigit}, but these return an \code{int} rather than a
|
\code{isdigit}, but these return an \code{int} rather than a
|
||||||
Boolean. The actual predicates are defined in \code{std::ctype} and
|
Boolean. The actual predicates are defined in \code{std::ctype} and
|
||||||
have the form \code{ctype::is(alpha,\ c)},
|
have the form \code{ctype::is(alpha, c)},
|
||||||
\code{ctype::is(digit,\ c)}, etc.
|
\code{ctype::is(digit, c)}, etc.
|
||||||
|
|
||||||
\section{Challenges}\label{challenges}
|
\section{Challenges}\label{challenges}
|
||||||
|
|
||||||
@ -491,18 +491,18 @@ have the form \code{ctype::is(alpha,\ c)},
|
|||||||
\item
|
\item
|
||||||
The factorial function from the example in the text.
|
The factorial function from the example in the text.
|
||||||
\item
|
\item
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
std::getchar()
|
std::getchar()
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
\item
|
\item
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
bool f() {
|
bool f() {
|
||||||
std::cout << "Hello!" << std::endl;
|
std::cout << "Hello!" << std::endl;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
\item
|
\item
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
int f(int x)
|
int f(int x)
|
||||||
{
|
{
|
||||||
static int y = 0;
|
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
|
examples. Categories come in all shapes and sizes and often pop up in
|
||||||
unexpected places. We'll start with something really simple.
|
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
|
The closest one can get to declaring a monoid in C++ would be to use the
|
||||||
(proposed) syntax for concepts.
|
(proposed) syntax for concepts.
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class T>
|
template<class T>
|
||||||
T mempty = delete;
|
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
|
An instantiation of the Monoid concept can be accomplished by providing
|
||||||
appropriate specializations and overloads:
|
appropriate specializations and overloads:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<>
|
template<>
|
||||||
std::string mempty<std::string> = {""};
|
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
|
imperative language, would likely be implemented by mutating some global
|
||||||
state, as in:
|
state, as in:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
string logger;
|
string logger;
|
||||||
|
|
||||||
bool negate(bool b) {
|
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
|
string argument, and pairing regular output with a string that contains
|
||||||
the updated log:
|
the updated log:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
pair<bool, string> negate(bool b, string logger) {
|
pair<bool, string> negate(bool b, string logger) {
|
||||||
return make_pair(!b, logger + "Not so! ");
|
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
|
produce a string, but we'd like to unburden it from producing a log. So
|
||||||
here's the compromise solution:
|
here's the compromise solution:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
pair<bool, string> negate(bool b) {
|
pair<bool, string> negate(bool b) {
|
||||||
return make_pair(!b, "Not so! ");
|
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
|
example. We have one function from string to string that turns lower
|
||||||
case characters to upper case:
|
case characters to upper case:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
string toUpper(string s) {
|
string toUpper(string s) {
|
||||||
string result;
|
string result;
|
||||||
int (*toupperp)(int) = &toupper; // toupper is overloaded
|
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
|
and another that splits a string into a vector of strings, breaking it
|
||||||
on whitespace boundaries:
|
on whitespace boundaries:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
vector<string> toWords(string s) {
|
vector<string> toWords(string s) {
|
||||||
return words(s);
|
return words(s);
|
||||||
}
|
}
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
The actual work is done in the auxiliary function \code{words}:
|
The actual work is done in the auxiliary function \code{words}:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
vector<string> words(string s) {
|
vector<string> words(string s) {
|
||||||
vector<string> result{""};
|
vector<string> result{""};
|
||||||
for (auto i = begin(s); i != end(s); ++i)
|
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
|
encapsulates a pair whose first component is a value of arbitrary type
|
||||||
\code{A} and the second component is a string:
|
\code{A} and the second component is a string:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A>
|
template<class A>
|
||||||
using Writer = pair<A, string>;
|
using Writer = pair<A, string>;
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
Here are the embellished functions:
|
Here are the embellished functions:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
Writer<string> toUpper(string s) {
|
Writer<string> toUpper(string s) {
|
||||||
string result;
|
string result;
|
||||||
int (*toupperp)(int) = &toupper;
|
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
|
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:
|
producing a log of those actions. Here's how we may do it:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
Writer<vector<string>> process(string s) {
|
Writer<vector<string>> process(string s) {
|
||||||
auto p1 = toUpper(s);
|
auto p1 = toUpper(s);
|
||||||
auto p2 = toWords(p1.first);
|
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
|
between the objects \code{int} and \code{bool}, even though the
|
||||||
embellished function returns a pair:
|
embellished function returns a pair:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
pair<bool, string> isEven(int n) {
|
pair<bool, string> isEven(int n) {
|
||||||
return make_pair(n % 2 == 0, "isEven ");
|
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
|
whatever. In particular, we should be able to compose it with our
|
||||||
earlier \code{negate}:
|
earlier \code{negate}:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
pair<bool, string> negate(bool b) {
|
pair<bool, string> negate(bool b) {
|
||||||
return make_pair(!b, "Not so! ");
|
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
|
regular functions, because of the input/output mismatch. Their
|
||||||
composition should look more like this:
|
composition should look more like this:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
pair<bool, string> isOdd(int n) {
|
pair<bool, string> isOdd(int n) {
|
||||||
pair<bool, string> p1 = isEven(n);
|
pair<bool, string> p1 = isEven(n);
|
||||||
pair<bool, string> p2 = negate(p1.first);
|
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
|
embellished functions that are composable according to our rules, and
|
||||||
return a third embellished function:
|
return a third embellished function:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A, class B, class C>
|
template<class A, class B, class C>
|
||||||
function<Writer<C>(A)> compose(function<Writer<B>(A)> m1,
|
function<Writer<C>(A)> compose(function<Writer<B>(A)> m1,
|
||||||
function<Writer<C>(B)> m2)
|
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
|
C++14-compliant compiler that supports generalized lambda functions with
|
||||||
return type deduction (credit for this code goes to Eric Niebler):
|
return type deduction (credit for this code goes to Eric Niebler):
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
auto const compose = [](auto m1, auto m2) {
|
auto const compose = [](auto m1, auto m2) {
|
||||||
return [m1, m2](auto x) {
|
return [m1, m2](auto x) {
|
||||||
auto p1 = m1(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}
|
In this new definition, the implementation of \code{process}
|
||||||
simplifies to:
|
simplifies to:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
Writer<vector<string>> process(string s) {
|
Writer<vector<string>> process(string s) {
|
||||||
return compose(toUpper, toWords)(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
|
identity functions! They have to be morphisms from type A back to type
|
||||||
A, which means they are embellished functions of the form:
|
A, which means they are embellished functions of the form:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
Writer<A> identity(A);
|
Writer<A> identity(A);
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
They have to behave like units with respect to composition. If you look
|
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
|
should pass its argument without change, and only contribute an empty
|
||||||
string to the log:
|
string to the log:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A> Writer<A> identity(A x) {
|
template<class A> Writer<A> identity(A x) {
|
||||||
return make_pair(x, "");
|
return make_pair(x, "");
|
||||||
}
|
}
|
||||||
@ -324,7 +324,7 @@ a -> Writer b
|
|||||||
We'll declare the composition as a funny infix operator, sometimes
|
We'll declare the composition as a funny infix operator, sometimes
|
||||||
called the ``fish'':
|
called the ``fish'':
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
(>=>) :: (a -> Writer b) -> (b -> Writer c) -> (a -> Writer c)
|
(>=>) :: (a -> Writer b) -> (b -> Writer c) -> (a -> Writer c)
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
It's a function of two arguments, each being a function on its own, and
|
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
|
Finally, the composition of the two functions is accomplished with the
|
||||||
help of the fish operator:
|
help of the fish operator:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
process :: String -> Writer [String]
|
process :: String -> Writer [String]
|
||||||
process = upCase >=> toWords
|
process = upCase >=> toWords
|
||||||
\end{Verbatim}
|
\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
|
can, however, be represented by a function that returns an embellished
|
||||||
type \code{optional}:
|
type \code{optional}:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A> class optional {
|
template<class A> class optional {
|
||||||
bool _isValid;
|
bool _isValid;
|
||||||
A _value;
|
A _value;
|
||||||
@ -446,7 +446,7 @@ public:
|
|||||||
As an example, here's the implementation of the embellished function
|
As an example, here's the implementation of the embellished function
|
||||||
\code{safe\_root}:
|
\code{safe\_root}:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
optional<double> safe_root(double x) {
|
optional<double> safe_root(double x) {
|
||||||
if (x >= 0) return optional<double>{sqrt(x)};
|
if (x >= 0) return optional<double>{sqrt(x)};
|
||||||
else return optional<double>{};
|
else return optional<double>{};
|
||||||
|
@ -265,7 +265,7 @@ snd (_, y) = y
|
|||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
In C++, we would use template functions, for instance:
|
In C++, we would use template functions, for instance:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A, class B> A
|
template<class A, class B> A
|
||||||
fst(pair<A, B> const & p) {
|
fst(pair<A, B> const & p) {
|
||||||
return p.first;
|
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'}.
|
\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
|
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
|
and \code{snd} is indeed \emph{better} than the two candidates I
|
||||||
presented before.
|
presented before.
|
||||||
|
|
||||||
@ -387,7 +387,7 @@ The \code{m} for the second example is similarly uniquely determined:
|
|||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}[commandchars=\\\{\}]
|
||||||
m (x, _, b) = (x, b)
|
m (x, _, b) = (x, b)
|
||||||
\end{Verbatim}
|
\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
|
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}
|
find some \code{m'} that would help us reconstruct \code{fst}
|
||||||
and \code{snd} from \code{p} and \code{q}?
|
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\\
|
union. For instance, a tagged union of an \code{int} and a\\
|
||||||
\code{char const *} could be implemented as:
|
\code{char const *} could be implemented as:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
struct Contact {
|
struct Contact {
|
||||||
enum { isPhone, isEmail } tag;
|
enum { isPhone, isEmail } tag;
|
||||||
union { int phoneNum; char const * emailAddr; };
|
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
|
functions. For instance, here's the first injection as a function
|
||||||
\code{PhoneNum}:
|
\code{PhoneNum}:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
Contact PhoneNum(int n) {
|
Contact PhoneNum(int n) {
|
||||||
Contact c;
|
Contact c;
|
||||||
c.tag = isPhone;
|
c.tag = isPhone;
|
||||||
@ -673,7 +673,7 @@ isomorphism is the same as a bijection.
|
|||||||
\section{Challenges}\label{challenges}
|
\section{Challenges}\label{challenges}
|
||||||
|
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\tightlist
|
\tightlist
|
||||||
\item
|
\item
|
||||||
Show that the terminal object is unique up to unique isomorphism.
|
Show that the terminal object is unique up to unique isomorphism.
|
||||||
\item
|
\item
|
||||||
@ -688,14 +688,14 @@ isomorphism is the same as a bijection.
|
|||||||
Show that \code{Either} is a ``better'' coproduct than \code{int}
|
Show that \code{Either} is a ``better'' coproduct than \code{int}
|
||||||
equipped with two injections:
|
equipped with two injections:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
int i(int n) { return n; }
|
int i(int n) { return n; }
|
||||||
int j(bool b) { return b? 0: 1; }
|
int j(bool b) { return b? 0: 1; }
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
|
|
||||||
Hint: Define a function
|
Hint: Define a function
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
int m(Either const & e);
|
int m(Either const & e);
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
|
|
||||||
@ -707,7 +707,7 @@ int m(Either const & e);
|
|||||||
\item
|
\item
|
||||||
Still continuing: What about these injections?
|
Still continuing: What about these injections?
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
int i(int n) {
|
int i(int n) {
|
||||||
if (n < 0) return n;
|
if (n < 0) return n;
|
||||||
return n + 2;
|
return n + 2;
|
||||||
|
@ -25,8 +25,8 @@ Library.
|
|||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
\noindent
|
\noindent
|
||||||
Pairs are not strictly commutative: a pair \code{(Int,\ Bool)} cannot
|
Pairs are not strictly commutative: a pair \code{(Int, Bool)} cannot
|
||||||
be substituted for a pair \code{(Bool,\ Int)}, even though they carry
|
be substituted for a pair \code{(Bool, Int)}, even though they carry
|
||||||
the same information. They are, however, commutative up to isomorphism
|
the same information. They are, however, commutative up to isomorphism
|
||||||
--- the isomorphism being given by the \code{swap} function (which is
|
--- the isomorphism being given by the \code{swap} function (which is
|
||||||
its own inverse):
|
its own inverse):
|
||||||
@ -114,7 +114,7 @@ can be defined alternatively as:
|
|||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}[commandchars=\\\{\}]
|
||||||
data Pair a b = P a b
|
data Pair a b = P a b
|
||||||
\end{Verbatim}
|
\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
|
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
|
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
|
\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
|
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
|
elements by combining two strings, name and symbol; and an integer, the
|
||||||
atomic number; into one data structure. We can use a tuple
|
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
|
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
|
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}):
|
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
|
This code is error prone, and is hard to read and maintain. It's much
|
||||||
better to define a record:
|
better to define a record:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
data Element = Element { name :: String
|
data Element = Element { name :: String
|
||||||
, symbol :: String
|
, symbol :: String
|
||||||
, atomicNumber :: Int }
|
, atomicNumber :: Int }
|
||||||
@ -193,7 +193,7 @@ data Element = Element { name :: String
|
|||||||
The two representations are isomorphic, as witnessed by these two
|
The two representations are isomorphic, as witnessed by these two
|
||||||
conversion functions, which are the inverse of each other:
|
conversion functions, which are the inverse of each other:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
tupleToElem :: (String, String, Int) -> Element
|
tupleToElem :: (String, String, Int) -> Element
|
||||||
tupleToElem (n, s, a) = Element { name = n
|
tupleToElem (n, s, a) = Element { name = n
|
||||||
, symbol = s
|
, 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).
|
can be nested, and the nesting order is irrelevant (up to isomorphism).
|
||||||
So we can, for instance, define a sum equivalent of a triple:
|
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
|
data OneOfThree a b c = Sinistral a | Medial b | Dextral c
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
and so on.
|
and so on.
|
||||||
@ -279,7 +279,7 @@ data Color = Red | Green | Blue
|
|||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
is the C++:
|
is the C++:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
enum { Red, Green, Blue };
|
enum { Red, Green, Blue };
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
An even simpler sum type:
|
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
|
can be translated to C++ using the null pointer trick to implement the
|
||||||
empty list:
|
empty list:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A>
|
template<class A>
|
||||||
class List {
|
class List {
|
||||||
Node<A> * _head;
|
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
|
interested in it. The second argument to \code{Cons} is bound to the
|
||||||
variable \code{t} (I will call these things variables even though,
|
variable \code{t} (I will call these things variables even though,
|
||||||
strictly speaking, they never vary: once bound to an expression, a
|
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
|
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
|
the clauses. If it was created using \code{Cons}, the two arguments
|
||||||
that were passed to it will be retrieved (and the first discarded).
|
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
|
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
|
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
|
no values --- and is therefore equivalent to \code{Void}. In other
|
||||||
words, \code{a*0 = 0}.
|
words, \code{a*0 = 0}.
|
||||||
|
|
||||||
@ -511,7 +511,7 @@ equation:
|
|||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}[commandchars=\\\{\}]
|
||||||
List a = Nil | Cons a (List a)
|
List a = Nil | Cons a (List a)
|
||||||
\end{Verbatim}
|
\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:
|
\code{x}, we get the equation:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\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
|
have to touch in Haskell vs. C++ or Java? (Even if you're not a
|
||||||
Haskell programmer, the modifications should be pretty obvious.)
|
Haskell programmer, the modifications should be pretty obvious.)
|
||||||
\item
|
\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},
|
isomorphism). Remember that \code{2} corresponds to \code{Bool},
|
||||||
according to our translation table.
|
according to our translation table.
|
||||||
\end{enumerate}
|
\end{enumerate}
|
@ -56,7 +56,7 @@ want all identity morphisms in C to be mapped to identity morphisms in
|
|||||||
D:
|
D:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}[commandchars=\\\{\}]
|
||||||
F ida = idF a
|
F id\textsubscript{a} = id\textsubscript{F a}
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
Here, \emph{id\textsubscript{a}} is the identity at the object \emph{a},
|
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}.
|
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
|
Here's the first case (I'm using Haskell pseudo-code to transform the
|
||||||
left hand side to the right hand side):
|
left hand side to the right hand side):
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
fmap id Nothing
|
fmap id Nothing
|
||||||
= { definition of fmap }
|
= { definition of fmap }
|
||||||
Nothing
|
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
|
in the middle --- here it was \code{Nothing}. The second case is also
|
||||||
easy:
|
easy:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
fmap id (Just x)
|
fmap id (Just x)
|
||||||
= { definition of fmap }
|
= { definition of fmap }
|
||||||
Just (id x)
|
Just (id x)
|
||||||
@ -239,7 +239,7 @@ fmap (g . f) = fmap g . fmap f
|
|||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
First the \code{Nothing} case:
|
First the \code{Nothing} case:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
fmap (g . f) Nothing
|
fmap (g . f) Nothing
|
||||||
= { definition of fmap }
|
= { definition of fmap }
|
||||||
Nothing
|
Nothing
|
||||||
@ -250,7 +250,7 @@ First the \code{Nothing} case:
|
|||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
And then the \code{Just} case:
|
And then the \code{Just} case:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
fmap (g . f) (Just x)
|
fmap (g . f) (Just x)
|
||||||
= { definition of fmap }
|
= { definition of fmap }
|
||||||
Just ((g . f) x)
|
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++
|
It's worth stressing that equational reasoning doesn't work for C++
|
||||||
style ``functions'' with side effects. Consider this code:
|
style ``functions'' with side effects. Consider this code:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
int square(int x) {
|
int square(int x) {
|
||||||
return x * x;
|
return x * x;
|
||||||
}
|
}
|
||||||
@ -281,7 +281,7 @@ double y = square(counter());
|
|||||||
Using equational reasoning, you would be able to inline \code{square}
|
Using equational reasoning, you would be able to inline \code{square}
|
||||||
to get:
|
to get:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
double y = counter() * counter();
|
double y = counter() * counter();
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
This is definitely not a valid transformation, and it will not produce
|
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
|
argument may be passed, with copy semantics, and with the resource
|
||||||
management issues characteristic of C++):
|
management issues characteristic of C++):
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class T>
|
template<class T>
|
||||||
class optional {
|
class optional {
|
||||||
bool _isValid; // the tag
|
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
|
\code{optional<T>}. Let's define its action on
|
||||||
functions:
|
functions:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A, class B>
|
template<class A, class B>
|
||||||
std::function<optional<B>(optional<A>)>
|
std::function<optional<B>(optional<A>)>
|
||||||
fmap(std::function<B(A)> f) {
|
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
|
This is a higher order function, taking a function as an argument and
|
||||||
returning a function. Here's the uncurried version of it:
|
returning a function. Here's the uncurried version of it:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A, class B>
|
template<class A, class B>
|
||||||
optional<B> fmap(std::function<B(A)> f, optional<A> opt) {
|
optional<B> fmap(std::function<B(A)> f, optional<A> opt) {
|
||||||
if (!opt.isValid())
|
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}
|
parameterize \code{fmap} with a \newterm{template template parameter}
|
||||||
\code{F}. This is the syntax for it:
|
\code{F}. This is the syntax for it:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<template<class> F, class A, class B>
|
template<template<class> F, class A, class B>
|
||||||
F<B> fmap(std::function<B(A)>, F<A>);
|
F<B> fmap(std::function<B(A)>, F<A>);
|
||||||
\end{Verbatim}
|
\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
|
functors. Unfortunately, there is a prohibition against partial
|
||||||
specialization of template functions in C++. You can't write:
|
specialization of template functions in C++. You can't write:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A, class B>
|
template<class A, class B>
|
||||||
optional<B> fmap<optional>(std::function<B(A)> f, optional<A> opt)
|
optional<B> fmap<optional>(std::function<B(A)> f, optional<A> opt)
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
Instead, we have to fall back on function overloading, which brings us
|
Instead, we have to fall back on function overloading, which brings us
|
||||||
back to the original definition of the uncurried \code{fmap}:
|
back to the original definition of the uncurried \code{fmap}:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A, class B>
|
template<class A, class B>
|
||||||
optional<B> fmap(std::function<B(A)> f, optional<A> opt) {
|
optional<B> fmap(std::function<B(A)> f, optional<A> opt) {
|
||||||
if (!opt.isValid())
|
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}
|
container. The implementation of \code{fmap} for \code{std::vector}
|
||||||
is just a thin encapsulation of \code{std::transform}:
|
is just a thin encapsulation of \code{std::transform}:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A, class B>
|
template<class A, class B>
|
||||||
std::vector<B> fmap(std::function<B(A)> f, std::vector<A> v) {
|
std::vector<B> fmap(std::function<B(A)> f, std::vector<A> v) {
|
||||||
std::vector<B> w;
|
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
|
We can use it, for instance, to square the elements of a sequence of
|
||||||
numbers:
|
numbers:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
std::vector<int> v{ 1, 2, 3, 4 };
|
std::vector<int> v{ 1, 2, 3, 4 };
|
||||||
auto w = fmap([](int i) { return i*i; }, v);
|
auto w = fmap([](int i) { return i*i; }, v);
|
||||||
std::copy( std::begin(w)
|
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
|
those words!), where there is a stronger distinction between type
|
||||||
arguments --- which are compile-time --- and values, which are run-time:
|
arguments --- which are compile-time --- and values, which are run-time:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class C, class A>
|
template<class C, class A>
|
||||||
struct Const {
|
struct Const {
|
||||||
Const(C v) : _v(v) {}
|
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
|
argument and essentially re-casts the \code{Const} argument without
|
||||||
changing its value:
|
changing its value:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class C, class A, class B>
|
template<class C, class A, class B>
|
||||||
Const<C, B> fmap(std::function<B(A)> f, Const<C, A> c) {
|
Const<C, B> fmap(std::function<B(A)> f, Const<C, A> c) {
|
||||||
return Const<C, B>{c._v};
|
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
|
If you're getting a little lost, try applying \code{BiComp} to
|
||||||
\code{Either}, \code{Const ()}, \code{Identity}, \code{a}, and
|
\code{Either}, \code{Const ()}, \code{Identity}, \code{a}, and
|
||||||
\code{b}, in this order. You will recover our bare-bone version of
|
\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
|
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
|
\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
|
instance declaration: a set of class constraints followed by a double
|
||||||
arrow:
|
arrow:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{minted}[breaklines]{text}
|
||||||
instance (Bifunctor bf, Functor fu, Functor gu) =>
|
instance (Bifunctor bf, Functor fu, Functor gu) =>
|
||||||
Bifunctor (BiComp bf fu gu) where
|
Bifunctor (BiComp bf fu gu) where
|
||||||
bimap f1 f2 (BiComp x) = BiComp ((bimap (fmap f1) (fmap f2)) x)
|
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
|
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
|
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
|
\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
|
it is. You need to enable a particular Haskell extension by including
|
||||||
this line at the top of your source file:
|
this line at the top of your source file:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{minted}{haskell}
|
||||||
{-# LANGUAGE DeriveFunctor #-}
|
{-# LANGUAGE DeriveFunctor #-}
|
||||||
\end{Verbatim}
|
\end{minted}
|
||||||
and then add \code{deriving Functor} to your data structure:
|
and then add \code{deriving Functor} to your data structure:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\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
|
Let's have a look at a tree data structure, which we would define in
|
||||||
Haskell as a recursive sum type:
|
Haskell as a recursive sum type:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
data Tree a = Leaf a | Node (Tree a) (Tree a)
|
data Tree a = Leaf a | Node (Tree a) (Tree a)
|
||||||
deriving Functor
|
deriving Functor
|
||||||
\end{Verbatim}
|
\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
|
support dynamic casting, so we'll make the destructor virtual (which is
|
||||||
a good idea in any case):
|
a good idea in any case):
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class T>
|
template<class T>
|
||||||
struct Tree {
|
struct Tree {
|
||||||
virtual ~Tree() {};
|
virtual ~Tree() {};
|
||||||
@ -361,7 +361,7 @@ struct Tree {
|
|||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
The \code{Leaf} is just an \code{Identity} functor in disguise:
|
The \code{Leaf} is just an \code{Identity} functor in disguise:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class T>
|
template<class T>
|
||||||
struct Leaf : public Tree<T> {
|
struct Leaf : public Tree<T> {
|
||||||
T _label;
|
T _label;
|
||||||
@ -370,7 +370,7 @@ struct Leaf : public Tree<T> {
|
|||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
The \code{Node} is a product type:
|
The \code{Node} is a product type:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class T>
|
template<class T>
|
||||||
struct Node : public Tree<T> {
|
struct Node : public Tree<T> {
|
||||||
Tree<T> * _left;
|
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
|
analyzing code in these terms, but it's a good exercise in categorical
|
||||||
thinking.
|
thinking.
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
template<class A, class B>
|
template<class A, class B>
|
||||||
Tree<B> * fmap(std::function<B(A)> f, Tree<A> * t) {
|
Tree<B> * fmap(std::function<B(A)> f, Tree<A> * t) {
|
||||||
Leaf<A> * pl = dynamic_cast <Leaf<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}:
|
Compare it with the Haskell implementation of \code{fmap}:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
instance Functor Tree where
|
instance Functor Tree where
|
||||||
fmap f (Leaf a) = Leaf (f a)
|
fmap f (Leaf a) = Leaf (f a)
|
||||||
fmap f (Node t t') = Node (fmap f t) (fmap f t')
|
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{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}
|
\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,
|
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},
|
function that takes \code{Writer a} and returns \code{Writer b},
|
||||||
exactly what \code{fmap} is supposed to produce.
|
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
|
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{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
|
the way Haskell implements polymorphic functions. It's called
|
||||||
\newterm{parametric polymorphism}, and it's a source of so 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
|
\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
|
Here's the typeclass defining a contravariant functor (really, a
|
||||||
contravariant \emph{endo}functor) in Haskell:
|
contravariant \emph{endo}functor) in Haskell:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
class Contravariant f where
|
class Contravariant f where
|
||||||
contramap :: (b -> a) -> (f a -> f b)
|
contramap :: (b -> a) -> (f a -> f b)
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
Our type constructor \code{Op} is an instance of it:
|
Our type constructor \code{Op} is an instance of it:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
instance Contravariant (Op r) where
|
instance Contravariant (Op r) where
|
||||||
-- (b -> a) -> Op r a -> Op r b
|
-- (b -> a) -> Op r a -> Op r b
|
||||||
contramap f g = g . f
|
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
|
second. Here's the appropriate typeclass taken from the
|
||||||
\code{Data.Profunctor} library:
|
\code{Data.Profunctor} library:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
class Profunctor p where
|
class Profunctor p where
|
||||||
dimap :: (a -> b) -> (c -> d) -> p b c -> p a d
|
dimap :: (a -> b) -> (c -> d) -> p b c -> p a d
|
||||||
dimap f g = lmap f . rmap g
|
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
|
Now we can assert that the function-arrow operator is an instance of a
|
||||||
\code{Profunctor}:
|
\code{Profunctor}:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
instance Profunctor (->) where
|
instance Profunctor (->) where
|
||||||
dimap ab cd bc = cd . bc . ab
|
dimap ab cd bc = cd . bc . ab
|
||||||
lmap = flip (.)
|
lmap = flip (.)
|
||||||
@ -677,7 +677,7 @@ data Pair a b = Pair a b
|
|||||||
Show the isomorphism between the standard definition of \code{Maybe}
|
Show the isomorphism between the standard definition of \code{Maybe}
|
||||||
and this desugaring:
|
and this desugaring:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
type Maybe' a = Either (Const () a) (Identity a)
|
type Maybe' a = Either (Const () a) (Identity a)
|
||||||
\end{Verbatim}
|
\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
|
\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.
|
type is different from other types.
|
||||||
|
|
||||||
\begin{wrapfigure}[13]{R}{0pt}
|
\begin{wrapfigure}[12]{R}{0pt}
|
||||||
\raisebox{0pt}[\dimexpr\height-0.75\baselineskip\relax]{
|
\raisebox{0pt}[\dimexpr\height-0.75\baselineskip\relax]{
|
||||||
\fbox{\includegraphics[width=40mm]{images/set-hom-set.jpg}}}%
|
\fbox{\includegraphics[width=40mm]{images/set-hom-set.jpg}}}%
|
||||||
\caption{Hom-set in Set is just a set}
|
\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
|
You can partially apply a C++ function using the template
|
||||||
\code{std::bind}. For instance, given a function of two strings:
|
\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) {
|
std::string catstr(std::string s1, std::string s2) {
|
||||||
return s1 + s2;
|
return s1 + s2;
|
||||||
}
|
}
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
you can define a function of one string:
|
you can define a function of one string:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
auto greet = std::bind(catstr, "Hello ", _1);
|
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
|
between. If you anticipate that the function you're defining will be
|
||||||
partially applied, you define it with multiple argument lists:
|
partially applied, you define it with multiple argument lists:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
def catstr(s1: String)(s2: String) = s1 + s2
|
def catstr(s1: String)(s2: String) = s1 + s2
|
||||||
\end{Verbatim}
|
\end{Verbatim}
|
||||||
Of course that requires some amount of foresight or prescience on the
|
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
|
glue code rather than abstract them into helper functions. Here's an
|
||||||
imperative-style implementation of the vector-length function in C:
|
imperative-style implementation of the vector-length function in C:
|
||||||
|
|
||||||
\begin{Verbatim}[commandchars=\\\{\}]
|
\begin{Verbatim}
|
||||||
double vlen(double * v) {
|
double vlen(double * v) {
|
||||||
double d = 0.0;
|
double d = 0.0;
|
||||||
int n;
|
int n;
|
||||||
|
Loading…
Reference in New Issue
Block a user