<div>Hi,</div>
<div> </div>
<div>I'm trying to characterise some strict monads to work with a particular lambda-calculus evaluator, as an alternative to CPS monad.</div>
<div> </div>
<div>In the thread "Stupid question #852: Strict monad" the implementation of some strict monads (and pseudo-monads, not meeting the identity laws) is discussed. It's clear form that thread that using pattern-matching in the (>>=) operation will force evaluation, then the Id monad defined with pattern-matching is strict (and it's indeed a monad):</div>
<div> </div>
<div>> newtype Id a = Id a<br>><br></div>
<div>> instance Monad Id where</div>
<div>> return = Id</div>
<div>> (Id a) >>= f = f a</div>
<div> </div>
<div>But it's impossible to derive a monad transformer from it, because you don't know the constructors of the monads you're transforming. I then tried to use strict application ($!). My first attempt was</div>
<div> </div>
<div>> newtype Strict a = InSt { outSt :: a }<br>><br></div>
<div>> instance Monad Strict where</div>
<div>> return = InSt</div>
<div>> m >>= f = (\x -> f x) $! (outSt m)</div>
<div> </div>
<div>which is not a monad (doesn't meet the left identity law).</div>
<div> </div>
<div> (return undefined) >>= (\x -> const (return 1) x) =/= (return 1)</div>
<div> </div>
<div>Then I wondered if it was enough to force the evaluation of the whole monad, instead of the value inside the monad, yielding the second attempt:<br><br>> newtype Strict a = InSt { outSt :: a }<br>><br>> instance Monad Strict where<br>
> return = InSt<br>> m >>= f = (\x -> f (outSt x)) $! m<br><br>I placed the outSt inside the anonymous function, leaving the monad on the right of the ($!). This meets the identity laws and surprisingly (I was expecting a lazy behaviour) implements strict semantics (it behaves like CPS, which is strict as well). A transformer from this monad can be easily written:<br>
<br>> newtype StrictT m a = InStT { outStT :: m a }<br>><br>> instance Monad m => Monad (StrictT m) where<br>> return = InStT . return<br>> m >>= t = InStT $ (\x -> x >>= (\a -> outStT $ t a)) $! (outStT m)<br>
><br>> instance MonadTrans StrictT where<br>> lift = InStT<br><br>Is it common practice to use this monad and this transformer? Why is it not in the standard library? I looked for this monad in the literature but I didn't find anything similar. It seems naive to me that this has never been previously described. Am I doing something wrong and this is not a monad at all?<br>
<br>Alvaro.<br></div>