[Haskell-beginners] Re: Forcing evalation in the IO Monad

Stephen Blackheath [to Haskell-Beginners] mutilating.cauliflowers.stephen at blacksapphire.com
Fri Apr 16 16:22:47 EDT 2010


All,

Philip's original question was:
> This question is so trivial it must have been answered before, but I
> have been googling all morning to no avail so please bear with me. I've
> been wading through mires of $! and seq, deepSeq, $!! etc.. and I have
> leaned a lot of useful stuff about lazy evaluation - but I haven't been
> able to solve my problem.. What I would like to do is to force an
> expression to be fully evaluated to normal form, from inside the IO
> monad, right there and then.
>
> For example, in GHCI, calling putStrLn does just what I want:
>
> Debug.Trace Prelude> let a = trace "Hello" 42
> Debug.Trace Prelude> putStrLn $ show a
> Hello
> 42
>
> Except that it only takes showable things, and it puts an annoying
> message on the screen.

Daniel - I get what you're saying...

Daniel Fischer wrote:
> Am Freitag 16 April 2010 21:14:54 schrieb Stephen Blackheath [to Haskell-
> Beginners]:
>> "evaluate x" is defined as "return $! x".
>
> Not quite:
>
> Prelude Control.Exception> evaluate (undefined :: Int) `seq` True
> True
> Prelude Control.Exception> ((return $! undefined) :: IO Int) `seq` True
> *** Exception: Prelude.undefined

I'll explain the difference for the benefit of beginners:

For IO actions that take arguments, there are two steps involved in
executing them in IO:
1. evaluate it to value of type "IO a", and
2. sequence it, which is a general monad term, but in the IO monad it
means that it will be actually executed.

IO actions that don't take arguments, like getLine, just go straight to
step 2.

For example, if you have 'putStrLn name', then

1. Evaluate:  Apply the argument name (type: String) to putStrLn (type:
String -> IO ()).  This gives a value of type IO ().  This is plain old
ordinary pure Haskell function evaluation.
2. Sequence:  The action embodied in the IO () value is actually
executed, and the name appears on the screen.

The difference between the two ways of forcing evaluation are, therefore:

"return $! x" does the forcing when it is evaluated.

"evaluate x" does the forcing when it is sequenced.

Since sequencing demands evaluation anyway, in all practical situations
these are equivalent.  But "evaluate x" works more like what you would
expect:  "evaluate (rnf x)" is exactly analogous to "putStrLn (show x)"
except without the screen output.


Steve


More information about the Beginners mailing list