You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: english/part1/ch01.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -111,7 +111,7 @@ There are two extremely important properties that the composition in any categor
111
111
When dealing with functions, the identity arrow is implemented as the 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:
Copy file name to clipboardExpand all lines: english/part1/ch04.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -103,7 +103,7 @@ We want to modify the functions `toUpper` and `toWords` so that they piggyback a
103
103
We will “embellish” the return values of these functions. Let's do it in a generic way by defining a template `Writer` that encapsulates a pair whose first component is a value of arbitrary type `A` and the second component is a string:
104
104
105
105
```cpp
106
-
template<classA>
106
+
template<typename A>
107
107
using Writer = pair<A, string>;
108
108
```
109
109
@@ -185,7 +185,7 @@ So here's the recipe for the composition of two morphisms in this new category w
185
185
If we want to abstract this composition as a higher order function in C++, we have to use a template parameterized by three types 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:
They have to behave like units with respect to composition. If you look at our definition of composition, you'll see that an identity morphism should pass its argument without change, and only contribute an empty string to the log:
241
241
242
242
```cpp
243
-
template<classA>
243
+
template<typename A>
244
244
Writer<A> identity(A x) {
245
245
return make_pair(x, "");
246
246
}
@@ -336,7 +336,7 @@ The particular monad that I used as the basis of the category in this post is ca
336
336
A function that is not defined for all possible values of its argument is called a partial function. It's not really a function in the mathematical sense, so it doesn't fit the standard categorical mold. It can, however, be represented by a function that returns an embellished type `optional`:
Copy file name to clipboardExpand all lines: english/part1/ch07.md
+9-9Lines changed: 9 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -194,7 +194,7 @@ This is definitely not a valid transformation, and it will not produce the same
194
194
Functors are easily expressed in Haskell, but they can be defined in any language that supports generic programming and higher-order functions. Let's consider the C++ analog of `Maybe`, the template type `optional`. Here's a sketch of the implementation (the actual 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++):
195
195
196
196
```cpp
197
-
template<classT>
197
+
template<typename T>
198
198
classoptional {
199
199
bool _isValid; // the tag
200
200
T _v;
@@ -210,7 +210,7 @@ public:
210
210
This template provides one part of the definition of a functor: the mapping of types. It maps any type `T` to a new type `optional<T>`. Let's define its action on functions:
211
211
212
212
```cpp
213
-
template<class A, class B>
213
+
template<typename A, typename B>
214
214
std::function<optional<B>(optional<A>)>
215
215
fmap(std::function<B(A)> f)
216
216
{
@@ -227,7 +227,7 @@ fmap(std::function<B(A)> f)
227
227
This is a higher order function, taking a function as an argument and returning a function. Here's the uncurried version of it:
@@ -295,15 +295,15 @@ By the way, the `Functor` class, as well as its instance definitions for a lot o
295
295
Can we try the same approach in C++? A type constructor corresponds to a template class, like `optional`, so by analogy, we would parameterize `fmap` with a [*template template parameter*]{.keyword #template_template_parameter}\index{template template parameter} `F`. This is the syntax for it:
296
296
297
297
```cpp
298
-
template<template<class> F, classA, class B>
298
+
template<template<typename> F, typename A, typename B>
299
299
F<B> fmap(std::function<B(A)>, F<A>);
300
300
```
301
301
302
302
\noindent
303
303
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:
304
304
305
305
```cpp
306
-
template<class A, class B>
306
+
template<typename A, typename B>
307
307
optional<B> fmap<optional>(
308
308
std::function<B(A)> f, optional<A> opt)
309
309
```
@@ -312,7 +312,7 @@ optional<B> fmap<optional>(
312
312
Instead, we have to fall back on function overloading, which brings us back to the original definition of the uncurried `fmap`:
If you are more comfortable with C++, consider the case of a `std::vector`, which could be considered the most generic C++ container. The implementation of `fmap` for `std::vector` is just a thin encapsulation of `std::transform`:
@@ -468,7 +468,7 @@ instance Functor (Const c) where
468
468
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:
469
469
470
470
```cpp
471
-
template<classC, class A>
471
+
template<typename C, typename A>
472
472
structConst {
473
473
Const(C v) : _v(v) {}
474
474
C _v;
@@ -479,7 +479,7 @@ struct Const {
479
479
The C++ implementation of `fmap` also ignores the function argument and essentially re-casts the `Const` argument without changing its value:
480
480
481
481
```cpp
482
-
template<class C, class A, class B>
482
+
template<typename C, typename A, typename B>
483
483
Const<C, B> fmap(std::function<B(A)> f, Const<C, A> c) {
Copy file name to clipboardExpand all lines: english/part1/ch08.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -218,7 +218,7 @@ As I mentioned before, one way of implementing sum types in C++ is through class
218
218
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 inanycase):
219
219
220
220
```cpp
221
-
template<classT>
221
+
template<typenameT>
222
222
struct Tree {
223
223
virtual ~Tree() {}
224
224
};
@@ -228,7 +228,7 @@ struct Tree {
228
228
The `Leaf` is just an `Identity` functor in disguise:
229
229
230
230
```cpp
231
-
template<classT>
231
+
template<typename T>
232
232
structLeaf : publicTree<T> {
233
233
T _label;
234
234
Leaf(T l) : _label(l) {}
@@ -239,7 +239,7 @@ struct Leaf : public Tree<T> {
239
239
The `Node` is a product type:
240
240
241
241
```cpp
242
-
template<class T>
242
+
template<typename T>
243
243
struct Node : public Tree<T> {
244
244
Tree<T> * _left;
245
245
Tree<T> * _right;
@@ -251,7 +251,7 @@ struct Node : public Tree<T> {
251
251
When implementing `fmap` we take advantage of dynamic dispatching on the type of the `Tree`. The `Leaf` case applies the `Identity` version of `fmap`, and the `Node` case is treated like a bifunctor composed with two copies of the `Tree` functor. As a C++ programmer, you're probably not used to analyzing code in these terms, but it's a good exercise in categorical thinking.
Copy file name to clipboardExpand all lines: english/part1/ch10.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -82,7 +82,7 @@ alpha :: F a -> G a
82
82
Keepin mind that it's really a family of functions parameterized by `a`.This is another example of the terseness of the Haskell syntax.A similar construct inC++ would be slightly more verbose:
0 commit comments