
Excerpts from Michael Snoyman's message of Sat Nov 07 22:55:14 +0100 2009:
On Sat, Nov 7, 2009 at 9:54 PM, Henning Thielemann < lemming@henning-thielemann.de> wrote:
On Sat, 7 Nov 2009, Jose Iborra wrote:
Sorry for the confusion, I never meant that c-m-e can show stack traces
for asynchronous exceptions. It can not.
My post was not related in any way to asynchronous exceptions. It's just the everlasting issue of the distinction of programming errors and exceptions.
I'm not sure if I managed to dispel your doubts, if not perhaps you could
make your points more clear.
I'm trying that for years now, repeatedly in this mailing list and on the Wiki: http://www.haskell.org/haskellwiki/Error http://www.haskell.org/haskellwiki/Exception I don't know how I can make it still clearer. It's just like concurrency vs. parallelism - somehow related, but it is important to distinguish them.
And yet if I use library ABC, which I expected to be error-free, and it in
fact has a programming error, is this an error or an exception from my point of view? Based on the definitions you posted, I believe the correct answer is "error." However, I'd much rather have a way to recover from that kind of error if it's logical.
For example, let's say that I'm writing a web browser in Haskell (it could happen). If there's an error in the HTTP library which causes it to die on certain types of headers, I'd much rather be able to tell the user sorry and let them continue browsing than to up and die with a "Prelude.head" message in their console.
If there is an "error" raised by the HTTP library on some headers, then this is a bug (a programming error), and so by using it your program is buggy too. However I would say that in this case wrapping the buggy function into safely-failing one is a valid temporary hack. A way to help distinguishing errors and exceptions would be to have pre and post conditions on function (as in "Static Contract Checking for Haskell"[1]). For instance head would have the following contract: {-# CONTRACT head :: { xs | not (null xs) } -> Ok #-} head :: [a] -> a head [] = error "head: empty list" head (x:_) = x When there is a pre-condition (or a contract) like here, it is a programming error to give an empty list to head. This means that checking if the list is empty must be done before the call. It has to statically deductible from the call site. If you write a function and cannot prove that you will not call head on the empty list then either you check before calling, or you use a safe-head function or you add a pre-condition to your function. [1]: http://www.cl.cam.ac.uk/~nx200/ -- Nicolas Pouillard http://nicolaspouillard.fr