The PyMonad Library
This will define a version of the sum() function that works with infinite sequences,
stopping the generation of values when the threshold had been met. This doesn't
seem to work because the pymonad library doesn't seem to handle infinite iterables
as well as it handles the internal List objects.
Functors and applicative functors
The idea of a functor is a functional representation of a piece of simple data.
A functor version of the number 3.14 is a function of zero arguments that returns
this value. Consider the following example:
pi= lambda : 3.14
We created a zero-argument lambda object that has a simple value.
When we apply a curried function to a functor, we're creating a new curried functor.
This generalizes the idea of "apply a function to an argument to get value" by using
functions to represent the arguments, the values, and the functions themselves.
Once everything in our program is a function, then all processing is simply a
variation on the theme of functional composition. The arguments and results
of curried functions can be functors. At some point, we'll apply a getValue()
method to a functor object to get a Python-friendly, simple type that we can use in
uncurried code.
Since all we've done is functional composition, no calculation needs to be done until
we actually demand a value using the getValue() method. Instead of performing
a lot of calculations, our program defines a complex object that can produce a value
when requested. In principle, this composition can be optimized by a clever compiler
or runtime system.
When we apply a function to a functor object, we're going to use a method similar
to map() that is implemented as the operator. We can think of the function
functor or map(function, functor) methods as a way to understand the role a
functor plays in an expression.
In order to work politely with functions that have multiple arguments, we'll use the
& operator to build composite functors. We'll often see functor & functor method
to build a functor object from a pair of functors.
We can wrap Python simple types with a subclass of the Maybe functor. The Maybe
functor is interesting, because it gives us a way to deal gracefully with missing data.
The approach we used in Chapter 11, Decorator Design Techniques, was to decorate
built-in functions to make them None aware. The approach taken by the PyMonad
library is to decorate the data so that it gracefully declines being operated on.