There are far more precise, formal descriptions out there; however, I’ll give a practical, if imprecise, description of monads that I believe (!) makes them easier to think about:
A monad is a datatype1 that allows us to: represent computations2 that have some structured3 result, and chain such computations together4
- The datatype defines two operations, which (in Haskell parlance) are called bind (>>=) and return. return places a value in the monad, and bind is used to pass this monadic value to another function. Implementations of these operations must satisfy certain laws.
- Some expression to be evaluated.
- The result has some additional context. For example, that context could be that the computation may fail (Haskell’s Maybe monad), or that it is non-deterministic (List), or that some interaction with the outside-world occurs (IO).
- Sequential composition. We can combine monadic values by passing them between functions that operate on them (using the bind operator)
Here’s an example in Haskell:
-- Placing a value inside the context of the Maybe monad, using 'return' x :: Maybe Int x = return 3 -- Let's define a function to operate on x -- It takes on a non-monadic value and produce another monadic value f :: Int -> Maybe String f a = return $ show a -- Lets apply function f to value 'inside' x using the bind operator applyFtoX :: Maybe String applyFtoX = x >>= f
As a bonus, here’s an example in Scala, inspired by some code I wrote recently at work that made use of the Writer monad from the Scalaz library. The Writer monad is useful for computations that accumulate some additional output alongside the result (e.g. logging).
Anyways, I hope this has been useful. If there is anything incorrect, don’t hesitate to mail me 🙂