On Fri, Mar 08, 2013 at 08:53:15PM -0800, Edward Z. Yang wrote:
> Are these equivalent? If not, under what circumstances are they not
> equivalent? When should you use each?
> 
>     evaluate a >> return b
>     a `seq` return b
>     return (a `seq` b)
> 
> Furthermore, consider:
[...]
>     - Does the underlying monad (e.g. if it is IO) make a difference?
[...]

Here's a monad transformer DelayT which adds an "evaluate" operation to any
monad.  Perhaps it will help in understanding the situation.

(NB it only has the desired behaviour for monads which must force x to at
least WHNF before they can perform the action associated with x >>= f, so
Identity won't do, for example).


% cat evaluate.hs && ghc -fforce-recomp evaluate.hs && ./evaluate
import Control.Monad.Trans.Class (lift, MonadTrans)

data DelayT m a = DelayT (m a) deriving Show

unlift :: DelayT m a -> m a
unlift (DelayT x) = x

instance Monad m => Monad (DelayT m) where
        return = lift . return
        x >>= f = lift $ unlift x >>= unlift . f

instance MonadTrans DelayT where
        lift = DelayT

evaluate :: Monad m => a -> DelayT m a
evaluate = lift . (return $!)

type M = Maybe

should_succeed :: Bool
should_succeed =  x `seq` () == ()
    where x :: DelayT M ()
          x = evaluate undefined

should_fail :: DelayT M ()
should_fail = evaluate undefined >> return ()

main = do putStrLn "Should succeed"
          print should_succeed
          putStrLn "Should fail"
          print should_fail
[1 of 1] Compiling Main             ( evaluate.hs, evaluate.o )
Linking evaluate ...
Should succeed
True
Should fail
evaluate: Prelude.undefined

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to