With the question Listing all the contents of a directory by breadth-first order results in low efficiencyI learned that the low efficiency is due to a strange behavior of t
The problem isn't the definition of sequence
, it's the operation of the underlying monad. In particular, it's the strictness of the monad's >>=
operation that determines the strictness of sequence
.
For a sufficiently lazy monad, it's entirely possible to run sequence
on an infinite list and consume the result incrementally. Consider:
Prelude> :m + Control.Monad.Identity
Prelude Control.Monad.Identity> runIdentity (sequence $ map return [1..] :: Identity [Int])
and the list will be printed (consumed) incrementally as desired.
It may be enlightening to try this with Control.Monad.State.Strict
and Control.Monad.State.Lazy
:
-- will print the list
Prelude Control.Monad.State.Lazy> evalState (sequence $ map return [1..] :: State () [Int]) ()
-- loops
Prelude Control.Monad.State.Strict> evalState (sequence $ map return [1..] :: State () [Int]) ()
In the IO
monad, >>=
is by definition strict, since this strictness is exactly the property necessary to enable reasoning about effect sequencing. I think @jberryman's answer is a good demonstration of what is meant by a "strict >>=
". For IO
and other monads with a strict >>=
, each expression in the list must be evaluated before sequence
can return. With an infinite list of expressions, this isn't possible.