[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