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

Josef Svenningsson
Wed, 7 Nov 2001 13:03:49 +0100 (MET)

On Tue, 6 Nov 2001, Levent Erkok wrote:

> On Tuesday 06 November 2001 01:20 pm, Josef Svenningsson wrote:
> > Let me elaborate on the strictness of a monad. The strictness of a monad
> > depends on how one implements the `bind' function. If the monad has a
> > strict bind then in examples like Koen's the print function will never be
> > called. If bind is lazy then the list will be produced incrementally.
> Can you elaborate? The bind for the Maybe monad is strict in its first
> argument. Is the Maybe monad strict in your sense? If that's the case,
> we should understand what is a bottom for the type IO a (for some type
> a), before deciding whether the IO monad is strict or not. Do you have
> a definition for that?
Yes, the Maybe monad is strict in my sense. So what I really mean by a
strictness of a monad is the strictness of the first argument of bind. I
usually think of it in terms of the state monad. Suppose we have:

type StateM s a = s -> (s,a)

The we can give two reasonable definitions of bind:

bind1 m f = \s -> let (s',a) = m s
		  in f a s'

bind2 m f = \s -> case m s of
		   (s',a) -> f a s'

bind1 corresponds to my intuitive notion of a lazy bind. bind2 is the
strict version.
In bind1, the expression m s will not be computed until a of s' is needed
in f. This is ofcourse nice since we all like to program in a lazy
language. But it can really bit when it comes to memory behavour.
bind2 on the other hand allows for efficient tail calls while it computes
m s right away, not leaving much room for lazyness.

But when it comes to the IO monad I'm not shure would be bottom for a type
IO a.

> Coming back to IO monad, I'd rather say it's eager (trying to avoid
> the word strict, but that's what I mean) in its actions, but certainly
> not in the values it produces. All the actions will be performed
> before you can view any results, but the results themselves are lazily
> produced. My favorite example is:
>        fixIO (\cs -> getChar >>= \c -> return (c:cs))
> you wait until getChar is done, but the final list is produced lazily.
Yes, you're absolutely correct. I must admit that my understanding of the
lazyness and eagerness of the different operations in the IO monad is
lacking. My statement of the IO monad being strict is an over

> I'd really love to see a more formal definition of the strictness of a monad,
> especically for internal monads like IO and ST.
So would I.