
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