Is it necessary that a monad "builds up a computation and then runs"? In fact it's very hard for a monad to do that because the type of bind is
(>>=) :: m a -> (a -> m b) -> m b
so you can really only make progress if you first build a bit (`m a`), then run it (to get `a`) then build the next bit (applying `a` to `a -> m b`), then run that. So "building" and "running" must necessarily be interleaved. It's an odd myth that "Haskell's IO purely builds an impure computation to run".