(Ebook) Learning Functional Programming: Managing Code Complexity by Thinking Functionally by Jack Widman ISBN 9781098111748, 1098111745 - Download the full ebook now for a seamless reading experience
(Ebook) Learning Functional Programming: Managing Code Complexity by Thinking Functionally by Jack Widman ISBN 9781098111748, 1098111745 - Download the full ebook now for a seamless reading experience
com
https://ebooknice.com/product/learning-functional-
programming-managing-code-complexity-by-thinking-
functionally-34883372
OR CLICK BUTTON
DOWLOAD EBOOK
(Ebook) Learning Functional Programming (Fifth Early Release) by Jack Widman ISBN
9781098111755, 9781098111748, 1098111753, 1098111745
https://ebooknice.com/product/learning-functional-programming-fifth-early-
release-43470558
ebooknice.com
https://ebooknice.com/product/functional-python-programming-efficient-python-
code-56115518
ebooknice.com
https://ebooknice.com/product/thinking-functionally-with-haskell-10508692
ebooknice.com
https://ebooknice.com/product/learning-java-functional-programming-55591800
ebooknice.com
(Ebook) Functional Programming in C#: How to write better C# code by Enrico Buonanno
ISBN 9781617293955, 1617293954
https://ebooknice.com/product/functional-programming-in-c-how-to-write-better-c-
code-6855324
ebooknice.com
(Ebook) Learning Scala: Practical Functional Programming for the JVM by Jason Swartz
ISBN 9781449367930, 1449367933
https://ebooknice.com/product/learning-scala-practical-functional-programming-
for-the-jvm-6545280
ebooknice.com
ebooknice.com
https://ebooknice.com/product/pro-functional-php-programming-application-
development-strategies-for-performance-optimization-concurrency-testability-and-
code-brevity-6766936
ebooknice.com
(Ebook) Functional Programming with C#: Create more supportable, robust, and
testable code (Second Early Release) by Simon J. Painter ISBN 9781492097013,
9781492097068, 1492097012, 1492097063
https://ebooknice.com/product/functional-programming-with-c-create-more-
supportable-robust-and-testable-code-second-early-release-44883856
ebooknice.com
Learning Functional
Programming
Managing Code Complexity by Thinking
Functionally
With Early Release ebooks, you get books in their earliest form—the
author’s raw and unedited content as they write—so you can take
advantage of these technologies long before the official release of these
titles.
Immutability
The single most important aspect of FP is immutability.1 Generally
speaking, this means a lack of change. Something is considered immutable,
if we cannot modify it in some way. In functional programming this means
a few things. Once a variable is set, its value cannot be changed. If x = 3 at
the beginning of a program, it has that value for the remainder of the
program. Does that mean that if a program is written in a functional style,
and a person’s age changes, this change cannot be modeled? Of course not.
That would be a disaster for functional programming. There are techniques
like copying that allow us to efficiently, manipulate our code, without ever
mutating state. Consider the following simple for loop in Java that prints the
numbers 0 to 99.
Java
This type of code occurs all the time. You might wonder how we could
possibly express this in an immutable way. It seems that the essence of this
code is the changing of the value of the variable i. A common approach in
FP is to use recursive functions. A recursive function is a function that calls
itself. In the case of the above code, you can put the code in a function and
then call the function on the next value of i, in each iteration. It might look
something like:
Java
void f(int i) {
if (i > 99) {
return;
}
else {
System.out.println( i)
return f(i+1)
}
}
f(0)
Now this code is a little longer but it does not mutate any state. If you know
a little about FP, you might know that the return type of void is a sure
giveaway that there will be side effects.2 A side effect is anything that
affects the program outside of the function. Things like writing to a file,
throwing an exception or modifying a global variable. The above example
is just meant to show one way of avoiding the mutation of state. You have
probably been mutating state your whole programming career and it likely
seems indispensible. But remember two things
NOTE
1) It feels very natural to mutate state.
2) Mutating state is a major cause of code complexity.
The good news is that with practice, the FP way will feel just as natural.
Let us consider another technique for avoiding the mutation of state.
Imagine you have an object, which has a property, or field and it changes.
Remember, I never made the claim that this never happens. That would be
absurd. The point is to model this situation without mutating a variable in
the code. Let us consider a Java example first.
Java
Python
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def main():
person = Person("John",22)
#One year later
changedPerson = Person("John",23)
One year passes and we need the person object to reflect this. But we can’t
modify the value age. So we create another immutable object with the age
variable initialized to 23
Let us now look at an example in Scala.
Scala
This line makes a new instance of Person and initializes age to 26. No
state has been mutated.
You may recall that I believe immutability to be the most important aspect
of FP. Lots of mutable state in a program is a source of many bugs. It’s
simply not easy to keep track of all the changing values. Above, we have
seen some examples of how to get around the apparent need to mutate state.
It takes some getting used to but with a little practice, using these
techniques may even start to seem natural.
Referential Transparency
You have seen some examples of immutability. Now we will look another
crucial piece of what makes up FP, Referential Transparency. We say an
expression is referentially transparent if we can replace it with its value
anywhere in the code. You might think, upon first hearing about this, that
you can always do this. Let us consider a simple example of a non
referentially transparent function.
Java
today()
If I call this function, and get, say May 29th, 2021, and I replace its body
with this value, and then call it tomorrow, I will get the wrong answer. It
might seem impossible to express this function as a referentially transparent
function but we will see how to approach this in a functional way later in
the book.
Here are a few more examples of non referential transparency:
A function that returns a random number. Obviously you can’t
replace the body of the function with a value you get when you call
it once.
A function that throws and exception. Exceptions are generally
avoided in FP. I will come back to that later.
The two function calls will very likely return different output values for the
same input value. This function is not pure. We have said mathematical
functions are pure. Well, programming has gained quite alot from this
mathematical approach. Functional programs are clean and pure and
elegant. The functional style of programming may take a little bit of getting
use to at first,but as we gradually move through the basic ideas of
functional programming in this book, you will little by little start thinking
like a functional programmer. Your functions will be pure and your code
will be clean. The biggest benefit, however, of writing functional programs
is that you will have a much stronger expectation that your programs will be
correct.
Let me make an important point here. We can’t ultimately just define what
FP is in a negative way. We can’t say its the same as ordinary programming
except that we leave out this and this and that and the other thing. The hard
part, the part accomplished by the many creators of FP is how to express
everything we need, in a functional way.
Higher Order Functions
Functional Programming is all about functions. What we want, in a
functional programming language, is the ability to treat functions as first
class citizens. This means we should be able to pass them as function
parameters and return them from functions as return values. Let’s discuss
why higher order functions are an important part of functional
programming. One key goal in functional programming is to get to the heart
of the matter. This means we need to be able to express concepts concisely
in our language. If we want to square every integer in a list, for example,
we shouldn’t have to loop through the list and modify each number by
squaring it. We should be able simply to directly apply a square function to
every element of the list simultaneously, as it were. The map function, in
many languages, allows us to do this. It allows us to work at a higher level
of abstraction. That higher level corresponds to a higher order function. We
will see this as a major theme as we proceed.
Example 1 (an imperative approach)
Python
def square(nums):
squared = []
for i in nums:
squared.append(i*i)
return squared
def square(nums):
return map(lambda n: n*n, nums)
Imagine you want to define your own if statement. Let’s call the function
myIf. You might want to add a logging line to every if statement, for
example. If you try the following, you will encounter a problem.
Scala
Can you see the problem with this definition? With eager evaluation, which
most common languages have, when the function is called, the first thing
that happens is that all of the parameters are evaluated. So in the case of
myIf, both the thenAction and the elseAction will be evaluated when you
only want one of them to be evaluated, depending on the condition variable.
However, with lazy evaluation, this would work. In this and related cases, it
would allow you to write your own control statements. Another benefit is
performance improvement in certain situations. Since the lazy code is only
evaluated when it is needed, it is often the case that it is actually evaluated
less than it would be in the eager evaluation case. This can speed up the
program.
In Scala we can use call by name parameters. In the code below, thenAction
and elseAction are only evaluated when they are needed. That is, they are
evaluated lazily. The following will work as expected.
Scala
But what does an arrow mean exactly? Well, it connects object A to object B.
Where the arrow starts and where the arrow ends is what’s most important, and this
relationship is the morphism. People tend to think of this arrow as a function, in
part because the above diagram makes it look like a function, and in most cases it is
a function. But there are categories where the morphisms are not functions.4 For
our purposes, we can think of a morphism between A and B as a function from A to
B, possibly with some conditions on the functions. Now if f is a morphism from A
to B, then A is called the domain of f and B is called the codomain of f. This
corresponds to the language used for functions.5
h(x) = g(f(x))
This may look mysterious but it is just the category theory way of saying that id is
A
the identity function on A. Category theorists tend to think not in terms of points,
but rather in terms of composition of functions. The above expression is how you
express the identity function in category theory in terms of composition. Instead of
saying identity morphism takes every point in the object to itself (because we don’t
think about the points), you say that when you compose the identity morphism with
another morphism, you get the original morphism back. This is actually a deep
point. Much of category theory is about expressing mathematical concepts through
the notion of composition.
Let’s look at some more examples. We will need something called a semigroup,
which you may have come across in a course on abstract algebra. It is really quite
simple. A semigroup has two main parts, a set of elements, (could be any non-
empty set) and a binary operation on the set. A binary operation, like multiplication
for whole numbers, or union for two sets, takes two things and returns a third thing.
There is one condition that must hold. The binary operation must be associative.
We will denote the binary operation by *.
* is associative means that for all x,y and z, we have:
x*(y*z) = (x*y)*z
NOTE
(In a semigroup, we often call the binary operation multiplication, even if it is not necessarily the
usual multiplication of numbers).
So the notion of morphism in this case, has to somehow capture the multiplicative
structure of the semigroup. In the following example, I’ll show you how this works.
Let S and S be two objects in the category Semigroup.
1 2
h(x*y) = h(x)*h(y)
What this essentially is saying is that the two semigroups have similar
multiplicative structure. It says if you want to know where h maps x*y, just look at
where h maps x and where h maps y and then multiply them together in S2. You
can think of the morphism as renaming the object it maps. In this case, x in S 1
Morphisms
Now if we take two types, say String and Int, how should we define a morphism
between them? Simply define a morphism from String to Int to be any function
which takes a String and returns an Int. So an example of a morphism between
these two types would be the length function. It takes a string, say “abc” and
returns an Int, in this case, 3. Now let’s give an example of the composition of two
morphisms. We know that in any category, if there is a morphism f : A → B and a
morphism g : B → C , then there must be a morphism h : A → C with h = g ∘ f .
Let’s take two morphisms that line up the right way and see what their composition
is.
f : String → I nt is defined by f (s) = s. length
g : I nt → I nt is defined by g(n) = n*n.
So f is the length function and g is the square function. What does their
composition look like?
g ∘ f (s) = (s. length)(s. length)
So we have our category Scal where the objects are types and for two types A and
B, the morphisms are functions that take an A and return a B.
NOTE
Once you have selected a programming language, Scala, in this case, all the category theory that is
applied to functional programming deals with this one category Scal, where the objects are Scala’s
types and the morphisms from A to B are functions that take an object of type A and return an
object of type B.
Functors
Functor is a funny word. It sounds like function and it is, indeed, a function. But it
is a very special kind of function. Before we define it, let’s look at some examples
in Scala that correspond to Functors. Some functors in Scala are List, Option and
Future.9 These examples have two things in common. First, they are generic types,
meaning that they take other types as parameters. You can’t just have a List in
Scala. You can have List[String], List[Int] or List[User], for example. List[String]
is not a functor. It is a type. But List by itself, is a functor. Same for the other two
examples. The second thing they have in common is that they all have a map
function. Let’s see an example:
Scala
List is a functor so it has a map function We will see where map comes from in
Category theory later in the chapter.
Now let’s define functor. I first need to specify two categories C and C . 1 2
Then a functor F from C to C is a function from the first category to the second
1 2
List[String])
2. F takes morphisms in C to morphisms in C . (What List does to a
1 2
morphism is trickier. It involves the map function and we will treat this
below.)
3. F (f ∘ g) = F (f ) ∘ F (g) whenever the morphism domains and codomains
of f and g line up.
This condition basically means that the two categories C and C have similar 1 2
structure with respect to morphisms. The idea to keep in mind when considering
functors is that they measure how similar two categories are.
Now we said earlier that the category we will be interested in is Scal.
NOTE
Don’t we need two categories to define a functor? Actually no. A functor can go from a category
to itself. Such a functor is called an endofunctor. So all the functors we will be considering, in the
category Scal, will be endofunctors.
Example 1 The List type constructor in Scala. (Notice I didn’t say type). What’s a
type constructor? List is not a type in its own right. It needs to take a type
parameter before it becomes a bonafide type. We can have a List of Strings, a list of
Ints etc. Once we pick a type parameter, say String, then we get the type
List[String]. So List by itself is called a type constructor. What are some other
examples like this in Scala? Option and Future to name a few.
In the category Scal, the above are examples of functors. List, Option and Future.
They are functors from the category Scal to itself. Remember, we called such a
functor an endofunctor. So List, Option and Future are examples of endofunctors,
and all endofunctors are functors.
This can be confusing so lets be very clear. In Scala, certain types have a map
function defined. (We will see that these are precisely the functors). So given a
functor, there is this map function in the background. And when we want to know
what the functor does to a morphism, we need to use the map function in a certain
way. We expressed this above with length but let us see what this looks like in the
general case.
Consider the morphism f : A → B, where A and B are two Scala types.
(i.e. two objects in the category Scal)
And let F : Scal → Scal be a functor from the category Scal to itself.
We write what F does to an object A as F[A] (think List[A] or Future[A] etc)
And to the morphism f, how do we write what F does?
If fa is an element of F[A], and f : A → B is a morphism
we write f a. map(f ). This function that takes fa to fa.map(f) is F(f).
In Scala, we don’t think of this function as, List(length),but rather as the map
function. There are actually many map functions, one for each functor. In Scala, we
think of this as just one map function, which can be applied to any container like
data structure. But in Category Theory, the map function is what you get when you
apply a functor to a morphism.
So this leads us to another, and more common way, of looking at functors. A
functor is simply an interface (or trait in Scala) that implements the map method.
We could even have called functor Mappable. And as we mentioned above, on a
higher level of abstraction, a functor is a way of measuring how similar two
categories are. Or in the case of endofunctors on the category Scal, a functor relates
the category Scal to a part of Scal.
I have now explained some of the major players in category theory: the category,
objects in the category, morphisms and functors. The reason I chose Scal as the
category to investigate is that functional constructions and idioms are more natural
in Scala than some of the other popular languages.11 In addition, the constructions
in Scala are so natural, they often almost look like pseudocode, which makes it
easier to give examples to a multilingual audience.
As we have seen, there are two ways of looking at a functor. We can represent
functor as a trait (or interface) that implements the map method or we can think of
it the way we think of it in category theory. From this perspective, a functor is a
function from the types of Scala to the types of Scala and it is also a function from
morphisms in the category Scal to other morphisms in Scal. In particular, if A and
B are two scala types, and f is a morphism from A to B, then F(f) is a morphism
from F[A] to F[B]. We could think of F as providing a context for two types and a
morphism between them. We start off working in A and in B and end up working in
F[A] and F[B]. So we have contextualized A and B. If I want to know what
represents the morphism f in the context F, we look at the morphism F(f) from F[A]
to F[B]. What is this morphism? Well if fa is an element of F[A], then
F (f ) takes f a to f a. map(f ).
Remember, that every Functor has a map method associated with it, so we can
always carry out the above expression. Let me give an example of the above. I can
use the functor List. In this example, A = Int and B = Int. F = List and let the
morphism
square : A → B be the square function.
Then F[A] = List[Int] and F[B] = List[Int] too.
What is F(square). That is to say, what is List(square)? Remember, for this we need
the map function that comes along with List (as it does with every functor). So we
have:
F (square)(f a) = f a. map(f ) or List(square)(f a) = f a. map(square).
This gives us:
List(square)(List(1, 2, 3, 4)) = List(1, 2, 3, 4). map(square) = List(1, 4, 9, 16)
Now we said that there are three properties a functor from category C to category D
must satisfy.
1) A functor F takes objects in C to objects in D. In the case of the category Scal,
this means F takes Scala types to Scala types.
2) F takes morphisms in C to morphisms in D.
3) A composition property, seen below:
F (f ∘ g) = F (f ) ∘ F (g) where f and g are morphisms.
Let us check this property for the functor List and two morphisms length and
square.12 So here length is a morphism from String to Int and square is a morphism
from Int to Int.
Plugging in the values, I have to show:
List(square ∘ length) = List(square) ∘ List(length)
Now the expression on the left takes an object of type List[String] to an object of
type List[Int] For example:
List(square ∘ length)(List(“ hello”, “ universe”)) =
So the two sides are equal. What we have shown, in this particular case, is in fact,
always true. For any functor F and two morphisms f and g, we always have:
F (f ∘ g) = F (f ) ∘ F (g)
So for example, this will hold for other functors such as Option and Future. Once
we know something is a functor, we know we can compose morphisms in this way.
Why do we care?
The Patterns
If you are unfamiliar with Some and None, see chapter two. Suppose we want to
add 1 to 8 and 2. Most languages don’t provide functor constructions out of the
box. Even Scala, which is fairly functional, doesn’t have this capability. But there is
a library called Cats13, which provides category theory constructs, as first class
objects, as it were. First, let’s look at the trait Functor, which comes with Cats.
Scala
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
We can see the map function, which every functor has. But what is F[_]?
F[_] is Scala’s way of expressing a type constructor, So the F, here, is what we are
thinking of as the functor. Now remember what we are trying to show. We want to
illustrate how composition of functors, which you always have, is useful. So back
to our example of listOfOptions.
The definition of the trait Functor in the scala library Cats, is much simplified for
our example. One method it comes with is compose. So in order to add one to the
numbers in the options, we can do the following.
Scala
Functor[List].compose[Option].map(listOption)(_ + 1)
We have a list of options of ints and we want to map over the Ints. So the above
expression lets us compose List and Option to get a new functor, and then use that
new functor’s map method to map over the ints with the anonymous function _ + 1,
which is just Scala’s way of writing an anonymous function that adds one. We
started with:
Monoids
As I mentioned earlier in the chapter, a semigroup is a set with an associative
operation on it. If a semigroup has an identify element, which means an element e,
in the semigroup, with the property that: e*x = x*e = x for all elements x the
semigroup, the semigroup is called a monoid.
In the following examples, I’ll show you some examples of monoids.
Example 1
Let M be the set of all non-negative whole numbers. Along with the operation
addition, this is a semigroup. But notice that 0 is in the set M. We know that if we
add 0 to any non-negative whole number, on the left or right, you get the original
whole number back.
NOTE
We say left side or right side because not all semigroups are commutative. Its not always true, in a
semigroup, that a*b = b*a.
This code computes the sum of a list of integers. Let’s analyze it from a functional
perspective. First, notice how it mutates state. The value of result continually
changes throughout the program. So does the value of i. Let us try to write a
functional version of this function that does not mutate state and also that uses an
abstraction like monoid to express the sum with a higher level of abstraction. There
is a function in functional programming called foldLeft (There is also a foldRight.
You will see this function with various names depending on the programming
languages. For example, foldLeft, foldl, fold, foldRight, foldr and fold). FoldLeft
essentially comes out of the concept of a monoid.
Consider the following monoid: the set of integers with addition as the operation
and 0 as the identity element. In any monoid we can create the foldLeft function.
(or foldRight, but I won’t keep repeating this). We combine the identity with the
first element of the monoid. Then we take the result of that and combine it on the
left (respectively right) with the next element in the monoid. We do this until there
are no more elements. We can describe this as follows: We are given a binary
operation, that is, one that combines two elements. And fold applies the operation
pairwise to get the combination of all the elements. Of course, in a commutative
monoid, foldLeft is equal to foldRight. In Java, there is a similar function called
reduce. Let’s see an example.
Java
Integer sumAll(List<Integer>lst) {
return lst.stream().reduce(0, Integer::sum);
}
In Scala, we have:
Scala
Natural Transformations
To keep things simple, we will not go into all the technical details that make up the
definition of natural transformations.14 My goal here is to give some idea of what a
monad is, in the context of category theory, and more importantly, to make clear
how they are useful in functional programming. If you wish, you can skip what
follows, if you are not interested in the theoretical underpinnings of the monad.
Then I will look at monads from a more practical, programming perspective. We
need natural transformations in order to define monads. It just so happens that there
is a way of thinking about natural transformations that is, well, natural. Functors, as
we know, are functions from one category to another category (for example, from
Scal to Scal). But we can change our perspective and build a new category where
the objects of the new categories are the functors from the original category. Let us
confine ourselves to endofunctors. Let us denote by End(C), the set of all functors
from C to C, for some category C.
Now we want these functors to be the objects in a new category, and to do so, we
need morphisms. That is, we need functions between endofunctors that satisfy the
rules for morphisms. Natural transformations in the category C correspond to
morphisms in this new category of endofunctors. What properties will these
morphisms have?
Let E , E and E be three endomorphisms of C. That is, they are three objects of
1 2 3
End(C).
And this composition is associative. These morphisms, in End(C) are what we call
natural transformations in the original category C. There is another definition of
them, which you would ordinarily see in a category theory book, but that is a bit
more involved. Thinking of them as morphisms in the category of endofunctors is
more straightforward. In other words, we start with a category C, form the category
End(C) and the morphisms of End(C) are natural transformations in C. Now how
NOTE
Remember, every monad is a monoid but not every monoid is a monad. A monad is a monoid with
some extra structure, which we defined above.
Now the road from a simple category to a monoid in the category of endofunctors
is a long one. I just wanted to give you some feel for what is involved. There are
ways of treating monads that are more practical and useful. In fact, there is a way to
get from the * operation of the monoid to a function called flatMap and to get from
the identity e in the monoid to a function called unit. And these two functions will
provide us with a more practical way of describing monads.
Now a monad is a monoid and it is also a functor. As a functor, it has a map method
(like all functors) and as a monad it also has a flatMap method.
Monads
We have hopefully gotten some idea of where monads come from. But what about
monads from a practical perspective? Do we need to deal with endofunctors
whenever we want to use a monad? And how are monads useful? It turns out that
there is a much simpler description of monads in the category Scal (or any other
category associated with a programming language). This simpler description has to
do with the functions flatMap and unit.
trait Monad[M[_]] {
def flatMap[A](ma: M[A])(f: A => M[B]): M[B]
def unit[A](a: A): M[A]
}
How should you think about monads? There is a mystery about them and based on
my description of where they come from in category theory, this is not surprising.
The definition of monad in a category theory is complex. There are many moving
parts. But if we think of the above trait, it becomes easier. The best way to think
about monads, from a functional programming perspective is that it provides a
context for an object. We can also think of it as adding additional structure to an
object.
Let’s start with unit, since this is simpler than flatMap. Unit takes an element of
type A and puts it into the context M[A], where M is the monad above. So for
example if M is Option, and we start with the string “abc”, we get the object
Some(“abc”). And this has type Option[String]. It’s not quite right to say that
Some(“abc”) is a string but we want to say something like this. Well we can say
this is a String in the context of Option. We have Optionized the String. Or we can
say we have added additional structure.
Now what about flatMap? Well let’s first consider the function map. That is
simpler. So we have something like:
Let ma be of type M[A]. Suppose we have a function f : A → B. Then ma.map(f)
will give us a value of type M[B] . map will basically take the value ma out of its
context M[A], apply f to it, get a value of type B and then wrap it in the context to
get a value of type M[B].
But suppose now we have ma again, a value of type M[A], but now we have
f : A → M[B]. This happens alot. M might be Option or List, for example. If we
try map, we get: ma.map(f). If you think this through, you will see map returns a
value of type M[M[B]]. And this is probably not what we want. This is where
flatMap comes into play. flatMap maps f over ma but then it flattens the result.
Let ma be of type M[A]. Let f : A → M[B].
Then ma.flatMap(f) will return a value of type M[B], not M[M[B]] .
Let’s see an example of this:
Scala
If we used map here instead of flatMap, we would have ended up with a List of
options of users. flatMap maps and then flattens, In this example, flattening means
taking the users out of the options. In general, flatMap is useful for chaining
together functions that involve monads.
Incidentally, you only need flatMap and unit to have a monad. If you have these
two, you can get map as follows:
Scala
So we can say a monad is a trait (or interface of some kind depending on the
programming language) that implements two methods. flatMap and unit. Also,
every monad is also a functor. So it must have a map function. And the above
expression shows how to get it from flatMap and unit.
To fully understand monad as it is in category theory would require more work. I
hope you have gotten a feel for the complexity involved in constructing a monad on
the one hand and the more straightforward programming approach where we model
a monad as an interface or trait that implements flatMap and unit.
Also, when somebody asks you what a monad is, you can answer It is a monoid in
the category of endofunctors and have, at least, a bit of an idea what that means.
Conclusion
You have learned what a category is, what the category Scal is, and some examples
of how to apply functors, natural transformations, monoids and monads to your
code. I will present more examples in the course of the book. It is important to
emphasize here that it is not absolutely necessary to learn category theory before
you learn about constructions like functors and monads and how to apply them to
your code, but I believe knowing where these constructions come from will give
more context and perhaps suggest novel ways of applying them to your code.
1 https://en.wikipedia.org/wiki/Software_design_pattern
2 https://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional-
ebook/dp/B000SEIBB8
3 Let us make clear here that objects, in this context, are distinct from objects in object oriented
programming.
4 As an example of this, consider the natural numbers. There is an arrow from m to n if m ≤ n. We get
composition from transitivity of ≤ and we get identity arrows from reflexivity. i.e. n ≤ n for all n.
5 See chapter 2.
6 See chapter 2.
7 So for example, Negative numbers with multiplication couldn’t form a semigroup because when you
multiply two negative numbers, you don’t get a nother negative number.
8 I call this category Scal because of the well established category Hask associated with the Haskell
language.
9 For more familiarity with these concepts, see chapter 2.
10 Unless its a list of functions. In this example, we do not mean a list of functions. We are applying List to
the function as a functor.
11 Opinion clearly labeled as such.
12 This part is a bit formula heavy. Feel free to skip it if its not your thing.
13 https://typelevel.org/cats
14 For more information on natural transformations, see
https://en.wikipedia.org/wiki/Natural_transformation. Natural transformations are complex.
About the Author
Jack Widman started his professional life as a mathematician in academia.
He studied and taught the intricacies of pseudo-compact topological groups,
as well as teaching calculus and discrete math courses. At the suggestion of
some friends, he decided to try out programming and see it this was his cup
of tea. It is now twenty-three years later and Jack has been designing and
writing code ever since. With a PhD in mathematics and twenty-three years
of software industry experience, Jack conceived of the idea to write a book
on functional programming, undoubtedly a subject with deep mathematical
roots, and this book you have in your hands is the result.
In his spare time, Jack enjoys Aikido, cycling, guitar and reading.
Another Random Scribd Document
with Unrelated Content
Undergoing more than his fair share of laceration, Peter crawled
under the brushwood. The three men crouched in the dim light that
filtered through the thicket, and silently contemplated the mouth of
the cave.
Prodding the ground with the haft of his spear, Jasper cautiously
entered the cave. For the first eight or ten paces the sides of the
tunnel-like entrance were fairly regular and less than a yard apart.
Then he found that the cave expanded both in height and width,
until it was impossible even with the spear to reach from one wall to
the other. Standing upright, Minalto found that he could just touch
the roof with his extended hand.
Instantly all thoughts of the pig vanished from the man's mind, and
again the long-dormant strain derived from his wrecking and
smuggling ancestors reasserted itself.
"How about it, Peter?" asked Alwyn, turning to the Wireless Officer.
The lid creaked on its hinges as Jasper threw it back. Then he gave
a howl of disappointment. All the chest contained was a rusty
cutlass, a clay pipe with a broken stem, and a number of brown
paper bundles containing candles all stuck together by the heat.
"So much for your treasure, Jasper!" said Burgoyne with a laugh.
"Never mind; we found something useful, the candles especially."
"No use stopping here," decided Alwyn. "Bend that rope round the
pig, Minalto, and we'll haul the brute out. Yes, bring the cutlass,
Peter, and a couple of packets of candles. The others can stop, in
case we want them here."
"Want them here?" repeated Mostyn.
"Rather," replied his chum. "This cave will make an ideal retreat if
we have to hide. I hope we shan't, but we must look things fairly in
the face. That's why I didn't want the brushwood cleared away. Had
it not been for the pig we should not have found the cave, and so
most likely no one else will."
"Yes, but how long ago we don't know, unless that cutlass gives us
a clue. I'll have a look at it when we get into the open. You see, the
person or persons who enlarged this place threw the excavated
material on a mound just outside. That shows they hadn't any idea
of concealing the cave. Since then this scrub has sprung up and
hidden it. Now then, Jasper, all ready? Heave away!"
"Now, where's that cutlass?" inquired Alwyn, after relating the story
of how their high expectations had been thwarted. "H'm, thought so.
Our predecessors on Swan Island weren't so very ancient after all.
This is a cutlass-bayonet, Peter, issued to the Navy in the late '70's
and '80's. That ring in the guard is where the muzzle went, but I see
the spring socket is rusted away. Nice job for you, Peter. You can
clean the thing up. It'll do to carve the Christmas dinner if we're
here long enough."
CHAPTER XXIV
The Cave proves Useful
During the two days following all hands were kept busily employed.
In addition to carrying out the usual routine, they made preparations
to lay in a stock of provisions. Mostyn tried his hand at obtaining salt
by evaporation, and succeeded in making about a pound of very
saline powder. Minalto cut up the porker, reserving some of the meat
for present use and pickling the rest. Hilda experimented with
making biscuits of taro root finely powdered and bruised between
two large stones.
"I believe it's our water-tank," declared Alwyn. "That's about where
the boat broke her back."
"In that case we'll have the thing ashore," declared Burgoyne. "It
would never do to leave such a monument to our mishaps lying in
such a conspicuous position."
Minalto swung off, and hurried to perform his task of look-out man.
In less than a quarter of an hour he was back again, breathless with
running.
Without undue delay all hands hurried to the summit of the hill,
Alwyn pausing only to scatter the burning logs over which the
morning meal was boiling, Hilda suffering the interruption of her
culinary task without protest.
From the elevated look-out post the vessel could be seen fairly
clearly. The morning was bright, with no sign of haze, and the craft
appeared nearer than she actually was. In spite of the light breeze
she was approaching rapidly, so that it was evident that she was
equipped with a motor.
She was then about a mile and a half or two miles off the northern
part of the island, shaping a course for the eastern side. She was a
fore-and-aft schooner, carrying jib-headed top-sails, and was of
about eighty tons displacement. She flew no colours.
"Too late, now, I'm afraid," replied his chum. "It will be as much as
we can do to transfer ourselves and our traps to the cave.... This
way down; in case they've a glass bearing on us."
Keeping to the south slope of the hill until the tree-tops shut out
the sight of the approaching vessel, the fugitives returned to the
camp.
There was much to be done in a very short time. The tent was
levelled and packed up in the smallest possible compass. The canvas
between the two upturned parts of the broken life-boat was
removed. The hot embers of the dying fire was carefully scattered,
lest they might kindle into flame and smoke. Then, heavily laden
with stores and provisions, the four hastened towards the cave.
"Ay, ay, sir," replied Minalto; then under his breath he added: "an' I
hope th' li'l ole cask'll poison the lot o' they."
It was now a slow and cautious business getting the stores and
gear into the cave, and in spite of every care Burgoyne noticed with
concern that the tracks under the scrub were by no means covered.
A keen Malay tracker would be able to find their retreat with little
difficulty. The only hope lay in the fact that the crew of the schooner
were unskilled in woodcraft, and that the broken twigs and
brushwood would escape notice.
"My festive Sparks, you are not," decided Burgoyne. "For the
present this is a one-man show. You stop here, and don't stir outside
till I come back. All being well, I'll return in twenty minutes, if not
before."
It was a tedious wait for the three who remained. Without means
of knowing the time, the minutes passed very, very slowly. Peter
tried to gauge the interval by observing the burning down of one of
the candles. The others waited and listened intently for any sounds
that might reach their ears from without the cave. Even the practical
Hilda Vivian looked anxious and worried. Mostyn, not usually
observant of people's characters, noticed that, and wondered
whether the girl was anxious on Burgoyne's account or merely
because of the peril that threatened her.
At length Minalto stood up, stretched his huge arms and picked up
the cutlass, which Mostyn had brought to a state bordering on
perfection, for the blade had been cleaned and sharpened, and the
hilt shone like a convex mirror in the candle-light.
Without further delay Jasper pulled aside the canvas screen, only
to collide violently with Alwyn Burgoyne.
"Eight of 'em, not a-countin' Black Strogoff, were you sayin', sir?"
inquired Minalto thoughtfully. "Sure, 'tes long odds, wi' only a pistol
an' a cutlass 'twixt three on us. Was there more on 'em left aboard,
sir?"
"I cannot say, Jasper. More than likely there were, but I didn't see
them. They'd hardly all go ashore."
"Ef us could slip along, like," resumed Jasper, "an' swim off to the
schooner—— When all's nice an' dark like."
Presently the four fugitives heard the sounds of men forcing their
way through the undergrowth, uttering fierce oaths in half a dozen
different languages and occasionally firing their rifles. During
intervals between the din, Black Strogoff's voice could be heard
shouting an ultimatum to the objects of his search, to the effect that
if they gave themselves up without further trouble, "including the
young woman" ("so they know," thought Alwyn), their lives would be
spared. Otherwise he, Strogoff, would search the island from end to
end and shoot the men down without mercy.
After the sounds of the pursuit had died away in the distance,
Jasper proposed that he should go out and see what was happening
in the lagoon.
"No, you don't," said Burgoyne decidedly. "Ten to one you'll play
straight into their hands, if you did. I shouldn't be at all surprised to
know that they had posted snipers at various intervals to pick us off
if we ventured out. Patience and discretion, Jasper. That's our motto
for the present. How about grub?"
Slowly the long day passed. At intervals the voices of the pirates
could be heard, as they returned to the boat apparently to hold a
council as to the next course to pursue. Black Strogoff had
abandoned his delivery of an ultimatum. He was still sanguine of
success, since the discovery of the wreckage of the life-boat and the
hot ashes of the camp-fire proved almost conclusively that his quarry
was on the island and unable to leave it.
"We'll have to be jolly careful with that light now," he observed. "A
glimmer escaping and shining on the brushwood would give the
show away in a brace of shakes. Put the candle in the old chest,
Jasper; that will screen it a bit."
After a cold supper Hilda and Mostyn dropped off into fitful
slumbers. Alwyn and Jasper remained on watch, straining their ears
to catch any sound that might indicate the presence and occupation
of their pursuers.
Soon there were no doubts on the matter. The rogues had not
gone on board the schooner but were carousing on shore. Some of
them in wanton mischief and with the lust of destruction had fired
the brush-wood. The roaring of the flames outvoiced that of the
pirates, but fortunately the nor'east wind kept the fire from
spreading towards the mouth of the cave.
"An' the li'l ole cask," said Minalto broodingly. "Ef I'd but taken ut
away...."
For the next hour the loud roar of the flames, as the fire
overwhelmed the coco-palms, completely muffled all other sounds,
but when at length, towards morning, the conflagration burnt itself
out, there was a strange uncanny silence.
"I think I will, then," replied Burgoyne gratefully, and for the next
two hours he slept like a log.
The slanting rays of the sun were penetrating the brushwood when
Alwyn awoke and lifted the canvas covering the entrance to the
cave. The air was thick with pungent smoke.
CHAPTER XXV
The Tables Turned
Gripping the cutlass, Jasper Minalto followed the Third Officer into
the open air, or rather to the edge of the belt of undergrowth that
marked the fugitives' hiding-place.
This part of the island had undergone a complete transformation.
Trees, scrub, and grass had vanished, leaving an expanse of
blackened, still smouldering ashes. The lagoon, previously screened
from the mouth of the cave, was fully exposed to an extent of
almost a mile. On it, riding to a cable that hung perpendicularly from
the hawse-pipe, was the schooner, with her sails lowered but loosely
furled in a way that no self-respecting seaman would have been
guilty of performing. There was the camp, too, with the shelter
constructed from the wreckage of the life-boat lying upon the
ground, and a fire still burning in the fire-place.
But what particularly attracted the attention of the two men was
the sight of half a dozen or more motionless figures lying in strange
attitudes upon the ground.
"By Jove!" exclaimed Burgoyne. "Minalto, my lad, your li'l ole cask
has done us a good turn. They're all dead drunk. Two, four, six, eight
of them. One's not accounted for. We'll risk that one. Stop here, and
don't let yourself be seen. I'll go back and bring Mostyn along."
"Bring as much rope as you can carry," said Alwyn, "and come
along. We've got them cold. Yes, and bring Minalto's spear. We may
have to do a bit of gentle persuasion in the clubbing line."
The three men advanced cautiously upon the silent forms of the
prostrate pirates, but it was not until they were within twenty paces
of their intended prey that Burgoyne checked his companions.
No words were necessary. The three men could see for themselves
what had happened.
There were eight pirates all dead. One, a Malay, was lying with his
head and shoulders in the still-smouldering embers. The others, all
bearing wounds of bullets or knives, had fought to a finish. Jasper's
li'l ole cask had vindicated its existence. Unused to spirits for months
past, the pirates had hailed the discovery of the keg with wild
delight. The potent stuff had made them mad drunk, and in their
beastly state of intoxication they had quarrelled, using knives and
rifles to back up their senseless arguments until all had fallen.
Apparently the Malay had survived the others, but had rolled
helplessly into the fire.
None of the three men felt any sense but that of gratitude for their
deliverance. Humane though they undoubtedly were, they had no
pity for the ruffianly crew now lying dead almost at their feet.
"Black Strogoff?"
"The boat isn't alongside. Come on; we'll find her along the beach."
Skirting the shore of the little creek, they gained the beach fronted
by the lagoon. Rather more than a stone's throw away was the
schooner's boat with her bow a good twelve feet from the water's
edge. Tugging and straining at the boat was Black Strogoff, trying in
vain to anticipate the rising tide by launching the small but heavily-
built dinghy into the water.
For answer the rogue whipped out an automatic, at the same time
kneeling behind the boat and resting the muzzle of the weapon on
the gunwale.
Without hesitation Mostyn and Jasper both raised their rifles and
took rapid aim. Both weapons barked simultaneously, even as Black
Strogoff wildly loosed ten rounds from his pistol. The next instant
the automatic was violently wrenched from the pirate-lieutenant's
hand, leaving Strogoff not only defenceless, but with a dislocated
wrist and his face cut in half a dozen places by fragments of the
splayed nickel bullet.
Strogoff had not the faintest desire to avail himself of the offer. He
knew that capture meant death at the rope's end.
"Launch the boat," continued Burgoyne. "We'll nab him long before
he gains the schooner."
"What are you going to do with him?" asked Peter, when by the
united efforts of the three men the boat was launched and the oars
manned.
Mostyn handed over the weapon. The rowers laid on their oars and
turned their heads to see what their companion was aiming at.
Black Strogoff was now only fifty yards ahead, swimming strongly
in spite of his broken wrist, but close behind him was a dark,
triangular-shaped object following the disturbed wake of the
swimmer.
The pirate, unconscious of the dire peril that threatened him, swam
steadily towards the schooner. Burgoyne, looking along the sights of
the rifle, hesitated to fire, for the shark and the swimmer were in
line with the muzzle. He might hit the shark, but the bullet would
then ricochet and settle Strogoff into the bargain.
Thirty seconds later the boat was over the spot, where an ever-
widening circle of ripples surrounded the blood-tinged patch that
indicated the manner of Black Strogoff's death.
Burgoyne, pale under his tan, slipped the safety-catch of his rifle,
laid the weapon in the stern-sheets, and resumed the tiller. As he did
so he noticed that the boat's bottom boards and gratings were
awash.
Kicking aside the stern-sheets grating, Alwyn felt for the plug. It
was in position and jammed hard into the bung-hole.
Peter and Jasper exchanged meaning glances. One of the two had
fired the shot that had completely penetrated both sides of the boat,
although one of the holes was above water-line. Each, by that
glance, tried to insinuate that the other was the culprit, at the same
time proving that the shot that had disabled Black Strogoff was his.
"We'll appraise responsibility when we've finished the job," declared
Burgoyne. "Now, steady all. Give way."
The boat, being bluff-bowed and laden, soon lost way, drifting idly
at a distance of about twenty yards from the schooner.
The boarders waited, finger on trigger, for a full minute. All was
quiet on board. Burgoyne judged it prudent to take possession of
the craft.
The door crashed to. Alwyn could hear the Chinaman hurriedly
barricading it. Then a spurt of flame leapt from one of the side
scuttles, and a revolver bullet chipped the mainmast.
"Keep where you are, Peter!" shouted Burgoyne. "I'll manage this
part of the show. Where's Minalto?"
"Hurt?"
"No, sir."
Burgoyne had already thrown himself flat upon the deck behind the
raised coaming of the main hatch. With his rifle by his side he
exposed no more than a part of his head, his right shoulder and arm
to the fire of the trapped Chinaman.
"'Tany rate," he soliloquized. "It's a fair scrap. One against one, not
three."
At the second shot the automatic fell to the deck and the hand was
withdrawn. Yells of pain issued from the deck-house.
From the spider band of the main-mast Alwyn took a coil of light
rope. With this he retraced his course, and, arriving at his "sniper's
post", proceeded to throw a bight of the rope over the rifle until it
engaged in the upturned bolt.
"When you've done smashing up his happy home, old bird!" sung
out Mostyn from the dinghy, "where do we come in?"
"You sit tight," replied Burgoyne. "The Chink very nearly pipped
me. He's as artful as a waggon-load of monkeys. I'll let you know
when you're wanted."
Placing his rifle by his side, Alwyn resumed his passive attitude
towards the silent and invisible Celestial. There could be very little
doubt, he reasoned, that Ah Ling had survived that fusillade.
Burgoyne sprang to his feet and looked over the side. Swimming
towards the little inlet was a Chinaman, bareheaded and with his
pigtail trailing in the water. Ah Ling, he knew, wore a pigtail. Very
few of the Chinese pirates did, but he was evidently not a believer in
the Western craze that was sweeping over the yellow republic. But it
might be just possible that there had been a third man on board the
schooner.
Unhesitatingly the Third Officer ran aft and peered into the riddled
deck-house. It was empty as far as human beings were concerned.
There were a couple of rifles and several pistols, while raised at an
angle of about 45 degrees to the floor was a sheet of steel that,
while not stout enough to stop a direct hit, was capable of deflecting
an obliquely striking bullet.
Unseen and unheard, Ah Ling had abandoned his defences and had
slipped over the taffrail. He was now within fifty yards of the shore,
where, to the horror of Burgoyne and his companions, Hilda Vivian
was standing gazing with perplexity at the captured schooner.
CHAPTER XXVI
The Fate of Ah Ling
Hitherto the girl's attention had been centred on the dinghy lying
alongside the schooner. She had heard the fusillade, and, unable to
remain any longer in suspense, she had left the cave and made her
way to the shore, fortunately giving the site of the camp and its
ghastly occupants a wide berth.
The fact that Peter and Jasper were in the boat reassured her to a
great extent, but she could not think of a satisfactory explanation of
Burgoyne's disappearance.
The dull thud of Ah Ling's wooden shoes upon the hard ground
guided them until with uncanny suddenness the sounds ceased. The
hitherto clearly defined trail of moisture dropping from the
Chinaman's sodden clothes also failed. Burgoyne, revolver in hand,
found himself standing at the junction of two forked paths, utterly
uncertain which direction to take.
He was afraid to shout to Hilda lest her reply should betray her
whereabouts. Listening intently, he could hear nothing of either the
pursued or the pursuer.
Well it was that Minalto had made no sound during his brief halt;
and so intent was Ah Ling upon stalking his foes that he was quite
unaware that one of them was stalking him.
During the Great War Jasper Minalto had seen some ghastly sights.
He had served on board a Q-boat when shells from a U-boat were
taking heavy toll of the devoted crew; he had seen the same Q-boat,
almost a wreck, suddenly spring into activity and send the Boche to
the bottom with one well-directed salvo. On another occasion the
same ship had rammed a U-boat with all hands. And on board the
Donibristle he had seen his unresisting comrades mown down by
shells from the pirate Malfilio. But never before had he knowingly
killed a man. He had assisted in the slaughter of dozens, but that
was hardly the same thing as personally sending a human being—
even though he were a Chinese pirate and ruffian—into the
unknown The thought of it made him feel sick. Like most men of
great stature, he was a child at heart, although brought up in a
rough school.
Totally unaware of the rapid events of the last few minutes, Alwyn
was closely following up his prey. Suddenly he noticed a movement
in the brushwood, not five yards ahead of him. Raising his revolver,
he sent a bullet straight at the writhing object. An unearthly groan
followed the report of the weapon, and a heavy body collapsed on
the hard ground.
Alwyn decided that his luck was right out. There was Hilda lying
murdered while her ruffianly assailant Ah Ling had escaped, and was
probably hiding safe from pursuit in the dense undergrowth that
covered the greater part of the island.
"I'll have the brute yet," he vowed, "even if we have to burn the
rest of the scrub."
"I'd give my right hand," continued the Third Officer, "to see Ah
Ling dead as a door-nail."
"Best let me, sir," interposed Jasper. "Seein' as' 'ow we might be
fallin' foul of that there Chink, an' I left me rifle up along."
Burgoyne glanced over his shoulder and met the stolid gaze of his
companion.
"You did this, then," he said.
"I never was axed; arter all, it wurn't much tu brag about, seeing
as 'ow I took 'im unawares-like. An' me bein' a quiet, well-disposed
man. But, there, sir; I did gi' ye my 'and when you offered yours, so
you'm no call to say I didn't warn 'ee."
For her injuries were found to be slight. Beyond the wound in her
shoulder and a slight gash on her forehead there were no evidences
of injury.
Deftly Burgoyne and Minalto dressed the hurts and bathed her
temples and wrists in cold water. By the time Peter Mostyn returned,
having scoured the greater part of the island in an unsuccessful
search, Hilda was able to sit up.
When Burgoyne's shouts warned her of her peril, the girl saw Ah
Ling's evil face as he swam towards the shore. Once she made up
her mind she started to return to the cave, but the Chinaman had
already cut off her retreat in that direction; or at all events she
would not have been able to regain the shelter without betraying its
whereabouts.
Then, as luck would have it, a boar dashed out of the undergrowth,
and, charging, threw her violently to the ground. She remembered
nothing more until she found herself on the shore with Burgoyne
and Jasper bathing her face and hands with cold water.
"Now, lads," said Burgoyne. "We've work to do, and the sooner the
better. We'll have to make the schooner habitable. I don't know what
she's like 'tween decks, but I can guess. And another thing: Miss
Vivian mustn't be allowed to see our old camp. We'll square things
up a bit, but that isn't everything."
"Come here a minute," he said, and led him to where one of the
men lay with his skull battered in, and a broken rifle by his side.
The treacherous Canuk bagman had met with his just deserts. It
was he who had betrayed the identity of Young Bill, hoping to curry
favour with the pirate leaders. Black Strogoff, in Ramon Porfirio's
absence, decided to act upon the information, but he was a few
hours too late. Miles's reward was not at all what he expected. He
was curtly ordered to join the band of pirates told off to man the
schooner that was to set sail in pursuit of the English girl and her
three companions. And the traitor was to a great extent responsible
for the disaster that had overtaken the pursuers, for it was he who
had found the li'l ole keg, and had started the quarrel when most of
the men were drunk with the well-matured rum.
CHAPTER XXVII
Farewell to Swan Island
"She'll lie there nicely," he decided, as the anchor was let go and a
stout warp taken ashore and made fast to a sturdy palm tree. "We'll
spend the rest of the day making everything ship-shape, but I don't
quite fancy sleeping aboard to-night."
Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.
ebooknice.com