[clean-list] Clean in the Real World
Marco Kesseler
m.wittebrood@mailbox.kun.nl
Tue, 16 Dec 2003 00:23:07 +0100
>On Mon, Dec 15, 2003 at 03:02:25PM +0100, Marco Kesseler wrote:
>> Apart from that, the same non-deterministic effects will occur in the
>> Monadic solution. The fact that this is theoretically allowed may not
>> help the average programmer in reasoning about his program.
>>
>> (which does _not_ imply that I am against soundness)
>>
>> And then, there is still the possibility to enforce catch statements
>> to always deliver the same constant expression on any exception.
>
>(Disclaimer: I haven't read the Imprecise Exceptions paper.)
>I think I understand why one might want to put exception handling in
>a monad. Because, to preserve equational reasoning, with the existence
>of non-deterministic exceptions such as e.g. InputOutputException (disk
>full, network disconnected, etc.), it is not even
>enough to say that a catch statement must not expose
>anything about the exception that has occurred. It must _also_
>be able to reproduce the same value, if it it returns a value,
>as the guarded expression would have if it _could_ have returned!
The imprecise exception paper distinguises three types of exceptions:
* disaster-type, like dividision by zero.
* alternative return, like when you throw an exception to indicate
that some search has failed.
* asynchronous exceptions, like "ctrl-C", or the I/O exceptions you
mention above.
The whole discussion until now does not have to do with the
asychronous exceptions. These are - by their very nature - related to
I/O and thus indeed belong to either I/O Monad or a unique "World"
state (well, in my view anyway).
The other two types - i.e. the synchronous ones - have the property
that they can be "replayed". They will happen again, if you evaluate
the same expression in exactly the same way.
The problem now is, that a compiler (for a functional language) does
not always have to evaluate the same expression in the same way. So
depending on the evaluation order that the compiler chooses, the
result of catching an exception may differ if you write down the same
expression twice.
To come back to your remark: in case of a synchronous exception,
there is no "real" return value, and there never will be, as the
exception will always happen. So the catch statement is free to
choose whatever value it wants.
>This implies that if a non-deterministic exception can possibly be
>thrown from a guarded expression, there are _only_ three possible
>"action outcomes" a handler can decide between:
>
>1. Retry evaluation
>2. Abort program entirely
>3. Throw an exception (possibly the same one that it has caught,
>possibly not)
>
>(Retry, Abort, or Throw)
>
>Right? It cannot return a value other than through (1) since this would
>violate equational reasoning. I think that is clear.
>
>While Bertrand Meyer (not a functional-ist per se, but an advocate
>of rigorous
>exception handling) might be happy with this tortuous arrangement, I
>personally am not. It seems too limiting (what about user interaction?)
>So it seems sensible to put _some_ exception handling in a
>non-referentially-transparent part of the system, which in the context
>of pure languages like Clean implies either (as a prior
>post suggested) in a separate process, or in a monad. I don't think
>uniqueness typing really works for this application, because of cases
>in which exceptions could occur all over the place, and therefore you'd
>have to pass around an exception-recording "World" state _everywhere_ -
>which rather changes the semantics of your program, as I previously argued.
This "trap" is basically the same for Monads, which is why I really
want to avoid such a solution.
>Of course, if you want to sensibly deal with out of memory exceptions or
>such things, they certainly can occur all over the place, in general.
Out-of-memory exceptions, and stack overflows are actually not of the
"replay" kind, so they can certainly not be handled by the solution
that I proposed. It is also not clear (to me) how they should be
handled if they were part of the IO Monad or the Unique World: (a)
you need some memory to actually execute a handler and (b) you cannot
manipulate the heap or the stack from within Clean or Haskell.
Marco
>--
>Robin
>
>"it's FREE and we get the ability to modify the source code ourselves,
>something that is extremely dangerous to do, was discredited decades ago..."
> - Howard Strauss writing in Syllabus magazine
> http://www.syllabus.com/article.asp?id=8460
>