
On Mon, 30 Mar 2009, Simon Marlow wrote:
Nicolas Pouillard wrote:
By reading the documentation of 'hGetLine' [1] one can see that this function can throw only an EOF exception so why not give it a type like below?
hGetLine :: Handle -> ErrorT EOF IO String
Since one will have to handle the error case it would be better to treat only the possible cases, no?
I'm afraid the documentation is incomplete. hGetLine can also fail because e.g. the device it was reading from has been unplugged, or it was reading from a network filesystem and the network has gone down. And there might be yet more errors to be invented in the future, so I'm not sure it would be a good idea to reflect this level of detail in the type.
Or the file could get read-protected. In principle I like to show the possible exceptions by types, but the point Simon raises is also important. I think IOError is good here and one must use the IOError analysis functions, to find out whether one can do something more specific in the case. For the default case there should be good possibilities to report the exception, e.g. translate it to the user language. For example when a file was not found, one can tell the user how to obtain it. But if the file is read-protected, a default message would suffice. The type IOError would still exclude an exception like "Parser failure". Thus explicit IOError is more descriptive than the implicit exceptions in IO monad today. It's still interesting how to handle sets of exceptions. If you use the exception type (Either ParserException IOError) then this is different from (Either IOError ParserException). I think we should use type classes for exceptions. Then you can use one type containing all exceptions in an application, but the type signature tells which exceptions are actually possible. E.g. parser :: ParserException e => ExceptionalT e ParserMonad a getLine :: IOException e => ExceptionalT e IO String fileParser :: (ParserException e, IOException e) => ExceptionalT e IO String