Simon Marlow wrote:
Anyway, I just wanted to point out that nowadays we have the option of
using imprecise exceptions to report errors in lazy I/O.

Is this really a solution? Currently, getContents reports no errors
but does perfect error recovery: the result of the computation prior to
the error is preserved and reported to the caller. Imprecise
exceptions give us error reporting -- but no error recovery. All
previously computed results are lost. Here's a typical scenario:
        do l <- getContents
           return (map process l)
If an error occurs reading lazy input, we'd like to log the error and
assume the input is terminated with EOF. If getContents raises an
imprecise exception, what do we do? return (map process (catch l (\e -> syslog e >> return [])))
That of course won't work: l is a value rather than an effectful
computation; besides; catch can't occur in the pure code to start
with. What we'd like are _resumable_ exceptions. The exception handler
receives not only the exception indicator but also the continuation
where the exception has occurred. Invoking this continuation means
error recovery. Resumable exceptions are used extensively in CL; they
are also available in OCaml. So, hypothetically we could write
        do l <- getContents
           resume_catch (return (map process l))
                (\e k -> syslog e >> k [])

Besides the obvious typing problem, this won't work for the reason
that exceptions raised in the pure code are _imprecise_ -- that is, no
precise continuation is available, even in principle.

Yes, I think I agree with that. Resumable exceptions don't make any sense for pure code (I can certainly imagine implementing them though, and they make sense in the IO monad).

But all is not lost: if an exception is raised during getContents for example, you still have the partial results: the list ends in an exception, and I can write a function that returns the non-exceptional portion (in IO, of course).

Haskell-Cafe mailing list

Reply via email to