Re: [Haskell-beginners] Re: [Haskell-cafe] try, seq, and IO

Op 2010-09-17 06:32, Dean Herington schreef:
At 10:54 AM +0200 9/16/10, Jeroen van Maanen wrote:
Op 2010-09-16 08:50, Jeroen van Maanen schreef: [...]
Gregs suggestion provided the way out: evaluate. My code now looks like this:
do let maybeUpdatedModel = f update startModel theCheckSum = maybe 0 checkSum maybeUpdatedModel logException exception = logger "Exception" [showString label, shows (exception :: SomeException)] >> return Nothing logger "Received update" [showString label, logs update] resultOrException <- try $ evaluate $ seq theCheckSum maybeUpdatedModel maybeNextModel <- either logException return resultOrException logger "Maybe next model" [showString label, logs maybeNextModel] -- ...
I still don't understand why evaluating maybeUpdatedModel to WHNF after seq evaluated theCheckSum to WHNF forces the lurking exception to the surface. Or is the phrase 'when the resultant IO action is executed' in the documentation of 'evaluate' significant here?
I still don't follow all your code, but presuming maybeUpdatedModel is of non-IO type, I'm guessing it's the evaluation of theCheckSum that causes evaluation of maybeUpdatedModel (which raises the exception).
What I don't understand is the difference between: try $ return $ seq theCheckSum maybeUpdatedModel or even try $! return $! seq theCheckSum maybeUpdatedModel and try $ evaluate $ seq theCheckSum maybeUpdatedModel How is it possible that the exception escapes the former two expressions, but gets caught by the third try? Cheers, Jeroen

On Friday 17 September 2010 13:17:30, Jeroen van Maanen wrote:
What I don't understand is the difference between:
try $ return $ seq theCheckSum maybeUpdatedModel
or even
try $! return $! seq theCheckSum maybeUpdatedModel
and
try $ evaluate $ seq theCheckSum maybeUpdatedModel
How is it possible that the exception escapes the former two expressions, but gets caught by the third try?
Cheers, Jeroen
It's quite devilish :) Well, the first and the third are rather straightforward. Let's start with the third. What that does is, evaluate (seq theCheckSum maybeUpdatedModel) to WHNF, if that throws an exception (of appropriate type, here SomeException), return (Left exception) else return (Right result). To evaluate `seq theCheckSum maybeUpdatedModel' to WHNF, theCheckSum has to be evaluated to WHNF (hence completely, since it's an Integer or something like), which in turn requires the complete evaluation of maybeUpdatedModel. The last throws an exception, that gets caught and wrapped in try, as expected and desired. The first one is `try (return thunk)' where thunk is "if needed, calculate `seq theCheckSum maybeUpdatedModel'". The return succeeds immediately, try wraps it in a Right and returns (Right thunk), as expected but not desired. The exception is thrown when you demand the evaluation of the thunk, after try has been left. Too lazy. Now the second one. try $! return $! seq t m === let z = return $! seq t m in z `seq` try z === let z = let v = seq t m in v `seq` return v in z `seq` try z === let { v = seq t m; z = v `seq` return v } in z `seq` try z === let v = seq t m in (v `seq` return v) `seq` try (return v) === ((t `seq` m) `seq` (return (t `seq` m)) `seq` try (return (t `seq` m)) So before try is even called, t has to be evaluated to WHNF, which throws an exception. Since it's thrown before try has been entered, try can't catch it. Too strict. So, first gives an uncaught exception after try has been left, second gives an uncaught exception before try has been entered. How do we get the exception to be thrown inside the try? That's easy. We mustn't allow try to return an exception-throwing thunk, so we need (return $! seq t m). But we mustn't cause the exception before try has been entered, so we need try $ return $! seq theCheckSum maybeUpdatedModel w00t
participants (2)
-
Daniel Fischer
-
Jeroen van Maanen