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

Daniel Fischer daniel.is.fischer at web.de
Fri Sep 17 09:18:21 EDT 2010


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



More information about the Beginners mailing list