[Haskell-cafe] Re: Takusen and strictness,
and perils of getContents
claus.reinke at talk21.com
Wed Mar 7 07:32:13 EST 2007
> 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.
i was wondering: could you perhaps use the old Hood Observe trick
to help you out? Hood wraps lazy sources in unsafePerformIO handlers
that log things as they are demanded, then passes them on. you might be
able to use the same to pass things on as they are demanded, while logging
exceptions and replacing exceptional with repaired or default values?
> 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've often wondered why exceptions are not optionally resumable,
with a handler that may decide to return or abort, depending on how
seriously the protected code is likely to be affected by the exception
in hand. that way, exception handling and normal processing would be
better separated, and simple fault tolerance easier to achieve, whereas
now the exception handler would have to know how to restart the
interrupted computation from scratch.
in terms of imprecise semantics, that might not be a problem, either:
yes, you can't guarantee that the same exception will be raised if you
repeat the experiment, but that is why the handler is in IO already.
no matter what exception and continuation it receives, if the exception
is non-fatal, it can log the problem and return, with a repaired value,
to the pure code that raised the exception.
in terms of stack-based implementation, it might be the simple difference
of clearing the stack in the handler, rather than in the raiser, giving the
handler the option to resume or abort the raiser. or is that too naive?-)
More information about the Haskell-Cafe