Lazy bind...

Lauri Alanko
Fri, 2 Aug 2002 15:57:54 +0300

On Tue, Jul 30, 2002 at 01:41:43PM +0100, MR K P SCHUPKE wrote:
> Is there any way to do a lazy bind operation, something like
>     a <- $ getLine
>     return (Constructor $ a)
> this works for computations in the IO monad :-
>     a <- unsafeInterleaveIO getLine
>     return (Constructor $ a)
> but I need to do this for a general monad M.

I don't think this is possible. In general, you have to write separate
strict and lazy binding operations. For instance, there are both ST and
LazyST for state transformer monads, and the latter's >>= operation is

Here's a concrete example for the basic state-carrying monad. (Not tested)

newtype State s a = State { unState :: s -> (a, s) }
getState = State (\s -> (s, s))
setState x = State (\s -> ((), x))
-- Monad.return
returnState a = State (\s -> (a, s))
-- strict Monad.>>=
State m `strictBindState` f 
  = State (\s -> case m s of (a, s') -> unState (f a) s')
-- lazy Monad.>>=
State m `lazyBindState` f 
  = State (\s -> case m s of ~(a, s) -> unState (f a) s')

As you can see, the difference between lazy and strict binding is an
inherent part of the definition of >>=, so there's no way to automatize
it. This is kind of a shame, for I too sometimes need both lazy and
strict versions of a monad transformer, but this requires two separate
types with different monad instances...

Lauri Alanko