
Hi Henning, I am going to make an "exception" here to my usual policy of not top-posting. Because I agree with everything you wrote. :) -Yitz On Jan 23, 2008 1:14 PM, Henning Thielemann wrote:
On Wed, 23 Jan 2008, Yitzchak Gale wrote:
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.
It's also terminology of Modula-3, from where Java inherits its exception mechanism. And probably its the same terminology in the ancestors of Modula-3.
In Haskell, the usage is, let's just say, unusual. :) Perhaps some technolinguist will have a good time studying it some day.
It would be good if Haskell libraries would separate the two issues, with whatever wording.
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.
You know, in Haskell we do not need a built-in exception handling facility because we can handle it with the elements of the language. Returning an exceptional value or throwing an exception is the same. We can only hide the exception propagation by appropriate binding of actions.
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.
Why not? We could design standard IO functions with improved API, with exceptions explicitly declared in the type. (One could also get rid of 'hFunction' names and use module name qualification instead.) In the future, when it becomes more usual to install a custom set of packages from Hackage instead of installing a large set of base libraries, people can more easily decide to use this library instead of System.IO. I think ByteString was long awaited and thus was adopted quickly by many programmers. I hope this happens for other solutions, too.
The reality is that Haskell's IO exception facilities have some rough edges.
I remember that I read somewhere that the Haskell veterans regret to having put so much things into IO, whenever they didn't know where to place them correctly. Exceptions are one such thing. Manipulating array in-place is another example. Putting 'fail' method into the Monad class is also acknowledged as a misconception today, and (I hope) most people agree, that there should be a separate class MonadError. Solutions already exist. STArray monad and runST can replace IOArray and unsafePerformIO in a safe way. Control.Monad.Error (which should be called Control.Monad.Exception with a distinct type for exceptions instead of Either) with ErrorT already allows to express in a type safe way what exceptions an action can throw. Maybe one day we succeed keeping exceptions completely out of IO and have them implemented by ErrorT/ExceptionT.