[haskell] What is a monad?

A Monad is an Applicative (i.e. something that you can lift binary -- hence, "n-ary" -- functions to,(1) and inject pure values into(2)) Functor (i.e. something that you can map over,(3) i.e. lift unary functions to(3)) with the added ability to flatten the nested datatype (with each of the three notions following its corresponding set of laws). In Haskell, this flattening operation is called join.

The general (generic, parametric) type of this "join" operation is:

join  ::  Monad m  =>  m (m a)  ->  m a

for any monad m (NB all ms in the type are the same!).

A specific m monad defines its specific version of join working for any value type a "carried" by the monadic values of type m a. Some specific types are:

join  ::  [[a]]           -> [a]         -- for lists, or nondeterministic values
join  ::  Maybe (Maybe a) -> Maybe a     -- for Maybe, or optional values
join  ::  IO    (IO    a) -> IO    a     -- for I/O-produced values

The join operation converts an m-computation producing an m-computation of a-type values into one combined m-computation of a-type values. This allows for combination of computation steps into one larger computation.

This computation steps-combining "bind" (>>=) operator simply uses fmap and join together, i.e.

(ma >>= k)  ==  join (fmap k ma)
{-
  ma        :: m a            -- `m`-computation which produces `a`-type values
  k         ::   a -> m b     --  create new `m`-computation from an `a`-type value
  fmap k ma :: m    ( m b )   -- `m`-computation of `m`-computation of `b`-type values
  (m >>= k) :: m        b     -- `m`-computation which produces `b`-type values
-}

Conversely, join can be defined via bind, join mma == join (fmap id mma) == mma >>= id where id ma = ma -- whichever is more convenient for a given type m.

For monads, both the do-notation and its equivalent bind-using code,

do { x <- mx ; y <- my ; return (f x y) }        --   x :: a   ,   mx :: m a
                                                 --   y :: b   ,   my :: m b
mx >>= (\x ->                                    -- nested
            my >>= (\y ->                        --  lambda
                         return (f x y) ))       --   functions

can be read as

first "do" mx, and when it's done, get its "result" as x and let me use it to "do" something else.

In a given do block, each of the values to the right of the binding arrow <- is of type m a for some type a and the same monad m throughout the do block.

return x is a neutral m-computation which just produces the pure value x it is given, such that binding any m-computation with return does not change that computation at all.


(1) with liftA2 :: Applicative m => (a -> b -> c) -> m a -> m b -> m c

(2) with pure :: Applicative m => a -> m a

(3) with fmap :: Functor m => (a -> b) -> m a -> m b

There's also the equivalent Monad methods,

liftM2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c
return :: Monad m =>  a            -> m a
liftM  :: Monad m => (a -> b)      -> m a -> m b

Given a monad, the other definitions could be made as

pure   a       = return a
fmap   f ma    = do { a <- ma ;            return (f a)   }
liftA2 f ma mb = do { a <- ma ; b <- mb  ; return (f a b) }
(ma >>= k)     = do { a <- ma ; b <- k a ; return  b      }

Examples related to haskell

Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell How can I get nth element from a list? How to split a string in Haskell? A monad is just a monoid in the category of endofunctors, what's the problem? Haskell: Converting Int to String What is Haskell used for in the real world? Getting started with Haskell What is the difference between . (dot) and $ (dollar sign)? What is a monad?

Examples related to functional-programming

Dart: mapping a list (list.map) Index inside map() function functional way to iterate over range (ES6/7) How can I count occurrences with groupBy? How do I use the includes method in lodash to check if an object is in the collection? Does Java SE 8 have Pairs or Tuples? Functional style of Java 8's Optional.ifPresent and if-not-Present? What is difference between functional and imperative programming languages? How does functools partial do what it does? map function for objects (instead of arrays)

Examples related to monads

A monad is just a monoid in the category of endofunctors, what's the problem? Monad in plain English? (For the OOP programmer with no FP background) What is a monad?

Examples related to terminology

The differences between initialize, define, declare a variable What is the difference between a web API and a web service? What does "opt" mean (as in the "opt" directory)? Is it an abbreviation? What's the name for hyphen-separated case? What is Bit Masking? What is ADT? (Abstract Data Type) What exactly are iterator, iterable, and iteration? What is a web service endpoint? What is the difference between Cloud, Grid and Cluster? How to explain callbacks in plain english? How are they different from calling one function from another function?