Non-monolithic version of 'sequence' for IO monad?

Koen Claessen
Tue, 6 Nov 2001 13:52:19 +0100 (MET)

Malcolm Wallace wrote:

 | > sequence :: (Monad m) => [m a] -> m [a]
 | > sequence = foldr (liftM2 (:)) (return [])

 | Are you *really* sure that the latter consumes its
 | entire input before producing any result?  It looks
 | pretty lazy to me, and I seem to be able to give it an
 | infinite list of computations and yet start receiving
 | results immediately....

This is not true, as the following example demonstrates:

  main :: IO ()
  main = sequence [ return i | i <- [1..] ] >>= print

The IO monad is strict. This means that one cannot look at
the result `a' of a computation of type `IO a' before all
the IO in that computation is done.

(Note that in other monads that are not strict, the above
computation works without problems.)

The function `unsafeInterleaveIO' in Hugs, GHC and HBC (and
NHC?) can turn a computation of type `IO a' into an "empty"
computation of type `IO a', which means we can start looking
at the result before any IO is done.

This operator is often used inside implementations to
implement functions like `hGetContents' and `readFile'.