Haskell Monads — Chaining with Context

Monads are often feared by newcomers, but the core idea is simple: a monad is a type that wraps a value with some context, and provides a way to chain operations that depend on that context.

The Maybe monad (handling absence)

HASKELL
-- Without monads:
lookupUser :: Int -> Maybe User
lookupUser id = ...

getAddress :: User -> Maybe Address
getAddress user = ...

getCity :: Address -> Maybe String
getCity addr = ...

-- Nested maybes (ugly):
getUserCity :: Int -> Maybe String
getUserCity id =
    case lookupUser id of
        Nothing  -> Nothing
        Just user ->
            case getAddress user of
                Nothing  -> Nothing
                Just addr -> getCity addr

-- With monads (do notation):
getUserCity :: Int -> Maybe String
getUserCity id = do
    user <- lookupUser id
    addr <- getAddress user
    getCity addr

The do notation chains operations — if any step returns Nothing, the whole chain short-circuits to Nothing.

The bind operator (>>=)

HASKELL
getUserCity :: Int -> Maybe String
getUserCity id =
    lookupUser id >>= \user ->
    getAddress user >>= \addr ->
    getCity addr

>>= (read "bind") takes a monadic value and a function that produces a monadic value, and chains them together.

List as a monad (nondeterminism)

HASKELL
-- Nondeterministic computation
pairs :: [(Int, Int)]
pairs = do
    x <- [1, 2, 3]
    y <- [10, 20]
    return (x, y)
-- [(1,10),(1,20),(2,10),(2,20),(3,10),(3,20)]

The IO monad

HASKELL
main :: IO ()
main = do
    putStrLn "What is your name?"
    name <- getLine
    putStrLn ("Hello, " ++ name ++ "!")

IO is a monad that sequences side effects in a pure language. getLine returns IO String — not a String — because it performs a side effect (reading from stdin). The do notation unwraps the values so you can work with them.

What makes a monad?

Any type that implements Monad must support:

HASKELL
class Monad m where
    return :: a -> m a          -- wrap a value
    (>>=)  :: m a -> (a -> m b) -> m b  -- chain operations

Tips

  • Start with Maybe — it's the simplest monad to understand.
  • do notation is syntactic sugar for >>= chains.
  • You don't need to understand the abstract math — just learn the patterns.
  • Monads are tools, not philosophy — use them when they simplify your code.

Next: io.