[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