
On Wed, Mar 25, 2009 at 7:02 PM, Gregory Petrosyan
First of all, thanks everybody for the discussion -- very interesting to read!
Apologies if this is off-topic a bit.
While reading, I have a feeling that proposed solutions are somewhat similar to checked exceptions. And IMO they turned out to be more harmful than useful.
Do you mean checked exceptions, or the proposed solutions? IMO the problem with checked exceptions is that they conflate two ideas by trying to use the existing exception framework to do something that can't otherwise be done by the language. This leads to something that doesn't work well for either use. Languages with checked exceptions usually use them for two purposes: 1. Exceptional conditions - disk full, CPU on fire, etc. 2. Error handling - invalid arguments to a function, attempt to invert non-invertible matrix, etc. In the first case, checked exceptions are a pain because there are so many different possible exceptional conditions to enumerate. Or alternatively you have an IOException that can be one of hundreds of actual exceptional conditions. This is exactly what regular exceptions are for, and in general there's little that can be done except terminate the program, except for certain special cases explicitly handled by the programmer. For the second case, checked exceptions actually work okay IMO. The syntax is a bit clunky, but they serve the purpose. That is, they specifically indicate what functions may fail and the failure mode. They also allow calling code to either handle it there or pass the error up to a higher level as appropriate. The syntax is usually ugly, though. Combining these two functions into one tool gives suboptimal results. If you're using checked exceptions for error handling, then you also end up using them for exception handling. That means you have IOException thrown by just about everything (and in theory any function in an imperative language could have an IOException due to hardware fault), leading to complex exception handlers with a half dozen case statements. There are a few reasons why Haskell's approach is (or at least can be) different. Compare the error handling models. Checked exceptions are bolted on to an existing tool attempting to make it serve a different purpose. It seems like a good idea, but ends up being painful because the two uses are at cross purposes. Instead of using a specific implementation and trying to alter it for another use, Haskell uses a very general facility, the type system, to solve one problem, and keeps the exception handling facility separate. Haskell's syntax for error handling is also much nicer. Nobody likes using methods that could possibly throw a dozen different exceptions, some of which are IOException and some are not. Actually, Haskell IO makes a big difference to this. Conceptually, you could think of Haskell functions as purely mathematical constructs. In particular, they can't interact with the physical world. This is true even for the IO monad. Exceptional conditions only arise when the Haskell runtime actually tries to *evaluate* an IO function. As a consequence exceptional conditions only arise as part of IO actions, and can only be handled by IO actions (because they're interacting with the run-time environment). This distinction makes it possible to enforce a separation between exceptions and error conditions, which is generally not possible in imperative languages where a function could fail either for a computational reason (divide by 0) or a hardware/runtime fault. Even in Haskell this separation isn't absolute. Programmer errors, such as dividing by 0, can and do lead to exceptional conditions. The proper way to handle dividing by 0 is to not do it in the first place, but if it happens because of a programming error, you've got an exception. Unfortunately this encourages programmers to think that handling the exception is the proper way to deal with this condition, but it isn't. I've only recently come around to the camp of treating exception handling and errors separately, so some of these thoughts may be a bit loose for the moment. In particular my thoughts from the above paragraph have only recently become clear. Henning T., FYI your constant advocacy has gotten at least one person around to this view. Cheers, John Lato