Haskell Monads Cheat Sheet
Covers the Monad typeclass, do-notation desugaring, Maybe/Either/List/IO monads, and the Reader/Writer/State monads for common effects.
3 PagesAdvancedJan 30, 2026
The `Monad` Typeclass
Every monad implements `>>=` (bind) and `return`/`pure`, satisfying the monad laws.
haskell
class Applicative m => Monad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a return = pure-- Monad laws (must hold for any correct instance):-- Left identity: return a >>= f == f a-- Right identity: m >>= return == m-- Associativity: (m >>= f) >>= g == m >>= (\x -> f x >>= g)
`do`-Notation Desugaring
`do` blocks are pure syntax sugar over chained `>>=` calls.
haskell
safeDivide :: Int -> Int -> Maybe IntsafeDivide _ 0 = NothingsafeDivide x y = Just (x `div` y)compute :: Maybe Intcompute = do a <- safeDivide 10 2 b <- safeDivide a 0 -- Nothing short-circuits the rest return (a + b)-- Desugars to:compute2 :: Maybe Intcompute2 = safeDivide 10 2 >>= \a -> safeDivide a 0 >>= \b -> return (a + b)
Maybe, Either, List & IO
The four monads you'll reach for constantly, each modeling a different kind of effect.
haskell
-- Maybe: optional/failable computationlookupUser :: Int -> Maybe StringlookupUser 1 = Just "Ada"lookupUser _ = Nothing-- Either: failable computation carrying an error valueparseAge :: String -> Either String IntparseAge s = case reads s of [(n, "")] -> Right n _ -> Left ("invalid age: " ++ s)-- List: nondeterministic computation (all combinations)pairs :: [(Int, Int)]pairs = do x <- [1, 2] y <- [10, 20] return (x, y) -- [(1,10),(1,20),(2,10),(2,20)]-- IO: sequencing side effectsmain :: IO ()main = do putStrLn "What's your name?" name <- getLine putStrLn ("Hello, " ++ name)
Reader, Writer & State Monads
From `mtl`/`transformers` — thread config, logs, or mutable state without explicit plumbing.
haskell
import Control.Monad.Readerimport Control.Monad.Writerimport Control.Monad.State-- Reader: implicit read-only environmentgreeting :: Reader String Stringgreeting = do name <- ask return ("Hello, " ++ name)-- Writer: accumulate a log alongside a resultlogStep :: Writer [String] IntlogStep = do tell ["starting"] tell ["computing"] return 42-- State: threaded mutable-looking statecounter :: State Int Intcounter = do n <- get put (n + 1) return nrunState counter 0 -- (0, 1)
Monad Glossary
Terms you'll see constantly in Haskell code and docs.
- >>= (bind)- sequences a monadic value into a function producing another monadic value
- >> (then)- like bind but discards the first result: `m >> n = m >>= const n`
- return / pure- lifts a plain value into the monad
- Functor / Applicative / Monad- increasingly powerful typeclasses; Monad requires both of the others
- fmap / <$>- Functor's map, applies a pure function inside the wrapper
- <*> (ap)- Applicative's apply, for functions wrapped in the same context
- Kleisli composition (>=>)- composes two `a -> m b` functions monadically
Pro Tip
When a do-block's type mismatches in a confusing way, mentally desugar it to explicit >>= calls — GHC's inferred types at each bind step are usually far easier to reason about than the compiler's error message on the whole do-block.
Was this cheat sheet helpful?
Explore Topics
#HaskellMonads#HaskellMonadsCheatSheet#Programming#Advanced#TheMonadTypeclass#DoNotationDesugaring#MaybeEitherListIO#Reader#DataStructures#CheatSheet#SkillVeris