Lazy bind...

Lauri Alanko la@iki.fi
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
lazy.

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
la@iki.fi