View on GitHub

Haskell

A mixture of Haskell quick reference guide, research logbook and tutorial full of external references

by Federico Mastellone

Monads

Why? The problem

We begin with an apparently fundamental conflict. A purely functional program implements a function; it has no side effect. Yet the ultimate purpose of running a program is invariably to cause some side effect: a changed file, some new pixels on the screen, a message sent, or whatever. Indeed it’s a bit cheeky to call input/output “awkward” at all. I/O is the raison d’ˆetre of every program. — a program that had no observable effect whatsoever (no input, no output) would not be very useful.

Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell

Haskell’s Monad class definition

Remember Functor and its primary operator <$> from here?

class Functor f where
        fmap :: (a -> b) -> f a -> f b
        (<$) :: a -> f b -> f a
(<$>) :: Functor f => (a -> b) -> f a -> f b

And Applicative and its primary function/operator <*> also from here?

class Functor f => Applicative f where
        pure :: a -> f a
        (<*>) :: f (a -> b) -> f a -> f b

The Monad class defines the basic operations over a monad, a concept from a branch of mathematics known as category theory. From the perspective of a Haskell programmer, however, it is best to think of a monad as an abstract datatype of actions.

Without further introduction this is a monad in Haskell, just a beefed up applicative functor:

class Applicative m => Monad m where
        (>>=) :: m a -> (a -> m b) -> m b
        (>>) :: m a -> m b -> m b
        return :: a -> m a 

The >>= function implements sequential composition, is a combinator used to combine/sequence/compose monadic actions and is often pronounced bind.

Historic note

For a long type Applicative was not a superclass of Monad but thankfully this was fixed with the AMP proposal. If you see code not making use of this much needed fix, please understand the past situation!

Wait, I’m slow

Compare the main composition functions of Functor, Applicative and Monad

(<&>) :: Functor m => m a -> (a -> b) -> m b -- Flipped version of Functor's <$>
(<**>) :: Applicative m => m a -> m (a -> b) -> m b -- A variant of <*> with the arguments reversed.
(>>=) :: Monad m => m a -> (a -> m b) -> m b -- Monadic bind

The Functor type class describes additional context around values using some type and the Applicative class let’s us compose Functors.

The monadic bind >>= is a stricter version of this two:

With Functor this extra structure is often thought of as a “container”, while with Monad it tends to be thought of as “side effects”.

TODO: The distinctive feature of Monad compared to other Functors is that it can embed control flow into the extra structure. The reason it can do this is that, unlike fmap which applies a single flat function over the entire structure, (>>=) inspects individual elements and builds new structure from that. https://stackoverflow.com/questions/3382210/monad-join-function

TODO: A Monad is something that "computes" when monadic context is collapsed by join :: m (m a) -> m a (recalling that >>= can be defined as x >>= y = join (fmap y x)). This is how Monads carry context through a sequential chain of computations: because at each point in the series, the context from the previous call is collapsed with the next. https://stackoverflow.com/questions/13352205/what-are-free-monads

Theory

Monads were originally invented in a branch of mathematics called category theory, which is increasingly being applied to describe the semantics of programming languages.

The usefullness of monads to describe composable “computations” was first described by Eugenio Moggi in Computational lambda-calculus and monads and also later wrote about how to to structure programs with monads in Notions of computation and monads. More from him at his personal page.

Those are not an easy read at all and are not specific about programming, Phil Wadler in Comprehending Monads describes the usefulness of monads in a programming context. He wrote several more papers like:

More from him at his personal page and all his monad related publications at this subpage.

TODO:

class Monad m => MonadFail m where
        fail :: String -> m a

TODO: unsafePerformIO !!!

TODO

Arrows, like Monads, are Monoids