The bind function seems remarkably similar like a composition function. And it helps in composing functions which return monads.
Is there anything more enlightening about monads than this idea?
Monads do compose, but the result might not be a monad. In contrast, the composition of two applicatives is necessarily an applicative.
In functional programming, a monad is a software design pattern with a structure that combines program fragments (functions) and wraps their return values in a type with additional computation.
A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.
monad, (from Greek monas “unit”), an elementary individual substance that reflects the order of the world and from which material properties are derived. The term was first used by the Pythagoreans as the name of the beginning number of a series, from which all following numbers derived.
Is there anything more enlightening about monads than this idea?
Yes, very much so!
Monadic binding is a way of composing functions where something else is happening over and above the application of a function to an input. What the something else is depends on the monad under consideration.
The Maybe
monad is function composition with the possibility that one of the functions in the chain might fail, in which case the failure is automatically propagated to the end of the chain. The expression return x >>= f >>= g
applies f
to the value x
. If the result is Nothing
(i.e. failure) then the entire expression returns Nothing
, with no other work taking place. Otherwise, g
is applied to f x
and its result is returned.
The Either e
monad, where e
is some type, is function composition with the possibility of failure with an error of type e
. This is conceptually similar to the Maybe
monad, but we get some more information about how and where the failure occured.
The List
monad is function composition with the possibility of returning multiple values. If f
and g
are functions that return a list of outputs, then return x >>= f >>= g
applies f
to x
, and then applies g
to every output of f
, collecting all of the outputs of these applications together into one big list.
Other monads represent function composition in various other contexts. Very briefly:
The Writer w
monad is function composition with a value of type w
being accumulated on the side. For example, often w = [String]
(a list of strings) which is useful for logging.
The Reader r
monad is function composition where each of the functions is also allowed to depend on a value of type r
. This is useful when building evaluators for domain-specific languages, when r
might be a map from variable names to values in the language - this allows simple implementation of lexical closures, for example.
The State s
monad is a bit like a combination of reader and writer. It is function composition where each function is allowed to depend on, and modify, a value of type s
.
The composition point of view is in fact quite enlightening in itself.
Monads can be seen as some of "funky composition" between functions of the form a -> Mb
. You can compose f : a -> M b
and g: b -> M c
into something a -> M c
, via the monad operations (just bind the return value of f
into g
).
This turns arrows of the form a -> M b
as arrows of a category, termed the Kleisli category of M
.
If M
were not a monad but just a functor, you would be only able to compose fmap g
and f
into something (fmap g) . f :: a -> M (M c)
. Monads have join :: M (M a) -> M a
that I let you define as an (easy and useful) exercise using only monad operations (for mathematicians, join
is usually part of the definition of a monad). Then join . (fmap g) . f
provides the composition for the Kleisli category.
All the funk of monadic composition can thus be seen to happen inside join
, join
represents the composition of side effects: for IO
it sequences the effects, for List
it concatenates lists, for Maybe
it "stops a computation" when a result is Nothing
, for Writer
it sequences the writes, for State
it sequences operations on the state, etc. It can be seen as an "overloadable semicolon" if you know C-like languages. It is very instructive to think about monads this way.
Of course, Dan Piponi explains this much better than I do, and here is some post of his that you may find enlightening: http://blog.sigfpe.com/2006/06/monads-kleisli-arrows-comonads-and.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With