
Henning Thielemann wrote:
http://www.haskell.org/haskellwiki/Exception http://www.haskell.org/haskellwiki/Error
The exact usage of the terms "error" and "exception" varies between programming languages. Your descriptions on the wiki follow Java usage, where Error and Exception are separate subclasses of Throwable. In Python, "exception" means the program flow construct, and "error" means a condition in which an exception is raised due to something going "wrong", so StandardError is a subclass of Exception. There are other conventions. In Haskell, the usage is, let's just say, unusual. :) Perhaps some technolinguist will have a good time studying it some day. I wrote:
If we start throwing IO exceptions for common and minor occurrences like no readline history available, libraries like this become impossible to write in Haskell. And code that has already been written becomes unusable.
...situations that cannot be avoided by the programmer but must be handled. An approved method to handle these cases are 'try' constructs.
Approved? The question is: when is it appropriate to use this technique in Haskell? Every function that can return more than one possible value has "situations that must be handled", but usually we will not throw exceptions.
Now if 'bracket' does not work for general MonadIO then it should be generalized.
'bracket', 'try', and 'catch' do need to be generalized. Realistically, that will not happen for a long time, if ever. The reality is that Haskell's IO exception facilities have some rough edges. They work great for asynchronous errors, which is what they were designed for. In general, whether or not IO exceptions are appropriate in Haskell is heavily dependent upon programming style. The only situation in which they are certainly called for is an asynchronous error. Perhaps also a non-error that satisfies all of the following conditions: E1) The function is strongly in the IO monad. E2) The condition is rare. E3) Sometimes the correct action would be to exit the program with an error message. In any other case, throwing an IO exception is an abuse that might ruin someone's program. If an IO exception is appropriate for the style of a particular program, it is easy for that program to provide one. When writing Haskell bindings for a library written in an imperative language, there is always a tension between providing a more idiomatic Haskell interface and faithfully reproducing the calling semantics of the library. When a C function returns an int to indicate various possible outcomes, that doesn't necessarily mean that it must throw an IO exception in Haskell, even if the author called the int an "error code". E2 and E3 do not hold for in the case of readline history - if were to throw an IO exception in the case of empty history, it would be obligatory for every program using it to wrap the function in a try. There is no way to express that in Haskell; you would have to write that requirement in a comment. That itself is evidence that the semantics of this language construct have been abused. (As contrasted with Java, for example, where ignoring the possible exception would cause the program to be rejected.) Regards, Yitz