[Haskell-cafe] To seq or not to seq, that is the question

Tom Ellis tom-lists-haskell-cafe-2013 at jaguarpaw.co.uk
Fri Mar 22 11:32:02 CET 2013


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



More information about the Haskell-Cafe mailing list