
with 6.10, the following does not typecheck: foo `Control.Exception.catch` \ _ -> return bar Ambiguous type variable `e' in the constraint: `Control.Exception.Exception e' It is probably bad programming style anyway but what is the workaround? I found some references (in list emails) to catchAny, ignoreExceptions but these don't seem to have made it? Best regards, J.W.

2008/10/7 Johannes Waldmann
with 6.10, the following does not typecheck:
foo `Control.Exception.catch` \ _ -> return bar
Ambiguous type variable `e' in the constraint: `Control.Exception.Exception e'
catch \(e :: SomeException) -> ... This requires language ScopedTypeVariables (and perhaps PatternSignatures). Of cause, you should try to be more specific about which exceptions you want to catch as e.g., Ctrl-C and many other things are also reported as exceptions.
It is probably bad programming style anyway but what is the workaround? I found some references (in list emails) to catchAny, ignoreExceptions but these don't seem to have made it?
Best regards, J.W.
_______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Johannes Waldmann wrote:
with 6.10, the following does not typecheck:
foo `Control.Exception.catch` \ _ -> return bar
Ambiguous type variable `e' in the constraint: `Control.Exception.Exception e'
It is probably bad programming style anyway but what is the workaround?
As long as you're aware that it is bad programming style. We deliberately didn't include an easy way to do this, because we want people to think about why they need to catch *all* exceptions (most of the time it's a bug). Cheers, Simon

On Wed, Oct 8, 2008 at 1:19 AM, Simon Marlow
Johannes Waldmann wrote:
with 6.10, the following does not typecheck:
foo `Control.Exception.catch` \ _ -> return bar
Ambiguous type variable `e' in the constraint: `Control.Exception.Exception e'
It is probably bad programming style anyway but what is the workaround?
As long as you're aware that it is bad programming style. We deliberately didn't include an easy way to do this, because we want people to think about why they need to catch *all* exceptions (most of the time it's a bug).
Since the above is bad form, what should I be doing? Could someone please provide some examples or point me at the list of exceptions that I can catch? What about catching multiple types of exceptions? Thanks, Jason

(+1) to that request - what is the "best practices" for portable exception handling code that straddles version 6.10, i.e. that compiles with compilers at either side with minimal fuss? I can imagine a couple of alternatives, but would like to hear what others are doing here. thanks --sigbjorn "likes backward code compatibility" On 11/1/2008 18:15, Jason Dagit wrote:
On Wed, Oct 8, 2008 at 1:19 AM, Simon Marlow
wrote: Johannes Waldmann wrote:
with 6.10, the following does not typecheck:
foo `Control.Exception.catch` \ _ -> return bar
Ambiguous type variable `e' in the constraint: `Control.Exception.Exception e'
It is probably bad programming style anyway but what is the workaround?
As long as you're aware that it is bad programming style. We deliberately didn't include an easy way to do this, because we want people to think about why they need to catch *all* exceptions (most of the time it's a bug).
Since the above is bad form, what should I be doing? Could someone please provide some examples or point me at the list of exceptions that I can catch? What about catching multiple types of exceptions?
Thanks, Jason _______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

I think the best way to get backwards compatibility is to flesh out
and use the extensible-exceptions package that Ian started, which
models extensible exceptions on top of the old exception mechanism.
Alternatively, you can decide not to use extensible exceptions and
have your package depend on base-3 instead of base-4.
For a library, however, I don't think there's a good solution, since
most of the time changing the exception mechanism for the library will
make the library incompatible with existing clients. I guess the best
way to deal with this is to properly use the package versioning policy
and hope that clients specify their dependencies precisely.
2008/11/2 Sigbjorn Finne
(+1) to that request - what is the "best practices" for portable exception handling code that straddles version 6.10, i.e. that compiles with compilers at either side with minimal fuss? I can imagine a couple of alternatives, but would like to hear what others are doing here.
thanks --sigbjorn "likes backward code compatibility"
On 11/1/2008 18:15, Jason Dagit wrote:
On Wed, Oct 8, 2008 at 1:19 AM, Simon Marlow
wrote: Johannes Waldmann wrote:
with 6.10, the following does not typecheck:
foo `Control.Exception.catch` \ _ -> return bar
Ambiguous type variable `e' in the constraint: `Control.Exception.Exception e'
It is probably bad programming style anyway but what is the workaround?
As long as you're aware that it is bad programming style. We deliberately didn't include an easy way to do this, because we want people to think about why they need to catch *all* exceptions (most of the time it's a bug).
Since the above is bad form, what should I be doing? Could someone please provide some examples or point me at the list of exceptions that I can catch? What about catching multiple types of exceptions?
Thanks, Jason _______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
_______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

On Sat, 2008-11-01 at 19:09 -0700, Sigbjorn Finne wrote:
(+1) to that request - what is the "best practices" for portable exception handling code that straddles version 6.10, i.e. that compiles with compilers at either side with minimal fuss? I can imagine a couple of alternatives, but would like to hear what others are doing here.
As far as I know there is no nice easy way to be compatible with both models. There's no subset you can stick to that works with both. In libraries like Cabal and other libs we've done things like: catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a #ifdef BASE4 catchIO = Exception.catch #else catchIO = Exception.catchJust Exception.ioErrors #endif catchExit :: IO a -> (ExitCode -> IO a) -> IO a #ifdef BASE4 catchExit = Exception.catch #else catchExit = ... etc ... #endif The point is, the old catch deals with just one exception type, while the new one works with various kinds of specific exception types. So you'd need one of these ifdefs for each type of exception you're catching. The other alternative is to just keep using the base 3 exceptions for a while and switch next time your lib makes a major api change. If you need to switch to base 4 for other reasons you can use the Control.OldExceptions if you don't want to switch to the new exceptions at the same time. I don't know much about the extensible-exceptions package, I'll let someone else explain about that. I was initially rather annoyed that the api has changed to much that it was not possible to make code work nicely without using cpp. On the other hand, the new exceptions api is a good deal nicer to use and is much more easily extensible. The old dynamic exceptions stuff was horrible. We used it in gtk2hs to implement the detailed exceptions that glib/gtk throws, but it constantly confused users. The new api also encourages you not to do silly things like catching all exceptions, known and unknown like the previous api did. This is important now that we have things like ^C being exceptions. Duncan

Jason Dagit wrote:
On Wed, Oct 8, 2008 at 1:19 AM, Simon Marlow
wrote: Johannes Waldmann wrote:
with 6.10, the following does not typecheck:
foo `Control.Exception.catch` \ _ -> return bar
Ambiguous type variable `e' in the constraint: `Control.Exception.Exception e'
It is probably bad programming style anyway but what is the workaround? As long as you're aware that it is bad programming style. We deliberately didn't include an easy way to do this, because we want people to think about why they need to catch *all* exceptions (most of the time it's a bug).
Since the above is bad form, what should I be doing? Could someone please provide some examples or point me at the list of exceptions that I can catch? What about catching multiple types of exceptions?
Let's distinguish two kinds of exception handling: 1. Cleaning up. If you want to catch errors in order to clean up - release resources, remove temporary files, that sort of thing - then use bracket or finally. Behind the scenes, these catch all exceptions, but crucially they re-throw the exception after cleaning up, and they do the right block/unblock stuff for asynchronous exceptions. 2. Recovery. You want to catch certain kinds of exception in order to recover and do something else, e.g. when calling getEnv. In that case, I recommend using try or tryJust. tryJust (guard . isDoesNotExistError) $ getEnv "HOME" it's good practice to separate the filter (the kinds of exception you're catching) from the code to handle them, and that's what tryJust does. There's some subtelty here to do with whether you need to be in "blocked" mode to handle the exception or not: if you're handling an exception you expect to be thrown asynchronously, then you probably want to use catch instead of try, because then the handler will run in blocked mode. But be careful not to tail-call out of the handler, because then the thread will stay in blocked mode, which will lead to strange problems later. A bit more background is here: http://hackage.haskell.org/trac/ghc/ticket/2558 (hmm, perhaps exception handlers should be STM transactions. Then you wouldn't be able to accidentally tail-call out of the exception handler back into IO code, but you would be able to re-throw exceptions. Just a thought.) As for the kinds of exception you can catch, nowadays you can catch any type that is an instance of Exception. A good place to start is the list of instances of Exception in the docs: http://www.haskell.org/ghc/dist/stable/docs/libraries/base/Control-Exception... although that only contains types defined by the base package. Others have commented on the backwards-compat issues, I don't have anything to add there. Cheers, Simon

On Mon, Nov 3, 2008 at 6:24 AM, Simon Marlow
Jason Dagit wrote:
On Wed, Oct 8, 2008 at 1:19 AM, Simon Marlow
wrote: Johannes Waldmann wrote:
with 6.10, the following does not typecheck:
foo `Control.Exception.catch` \ _ -> return bar
Ambiguous type variable `e' in the constraint: `Control.Exception.Exception e'
It is probably bad programming style anyway but what is the workaround?
As long as you're aware that it is bad programming style. We deliberately didn't include an easy way to do this, because we want people to think about why they need to catch *all* exceptions (most of the time it's a bug).
Since the above is bad form, what should I be doing? Could someone please provide some examples or point me at the list of exceptions that I can catch? What about catching multiple types of exceptions?
Let's distinguish two kinds of exception handling:
Thanks. This helps a lot. Mind if I put it somewhere, such as on the wiki?
As for the kinds of exception you can catch, nowadays you can catch any type that is an instance of Exception. A good place to start is the list of instances of Exception in the docs:
http://www.haskell.org/ghc/dist/stable/docs/libraries/base/Control-Exception...
although that only contains types defined by the base package.
Others have commented on the backwards-compat issues, I don't have anything to add there.
Ah, but I had one more question that I don't think anyone has answered yet. That is, how to deal with multiple types of exceptions. Suppose, as a concrete example, that I was looking out for both ExitCode and PatternMatchFail exceptions. Maybe I'm being naive, but it seems like I'm in that situation again where I have to catch all and then check if fromException succeeds on either PatternMatchFile or ExitCode types. And then throw if it both give Nothing? Thanks! Jason

On Mon, Nov 3, 2008 at 9:34 AM, Jason Dagit
Ah, but I had one more question that I don't think anyone has answered yet. That is, how to deal with multiple types of exceptions. Suppose, as a concrete example, that I was looking out for both ExitCode and PatternMatchFail exceptions. Maybe I'm being naive, but it seems like I'm in that situation again where I have to catch all and then check if fromException succeeds on either PatternMatchFile or ExitCode types. And then throw if it both give Nothing?
I haven't tried this, so it may not work:
data MyException = MyArithException ArithException | MyIOException IOException deriving Typeable
instance Exception MyExcpetion where toException (MyArithException e) = toException e toException (MyIOExcpetion e) = toException e fromException se = case fromException se of Just e -> Just $ MyArithException e Nothing -> case fromException se of Just e -> Just $ MyIOException e _ -> Nothing <<<<< Then anyone can catch your exceptions by catching the ArithException or IOException as normal, and you can catch IOExceptions and ArithExceptions into your own custom type. -Antoine

On 11/3/2008 07:34, Jason Dagit wrote:
....
Ah, but I had one more question that I don't think anyone has answered yet. That is, how to deal with multiple types of exceptions. Suppose, as a concrete example, that I was looking out for both ExitCode and PatternMatchFail exceptions. Maybe I'm being naive, but it seems like I'm in that situation again where I have to catch all and then check if fromException succeeds on either PatternMatchFile or ExitCode types. And then throw if it both give Nothing?
One way to do this now is to use Control.Exception.catches: catches :: IO a -> [Handler a] -> IO a data Handler a where Handler :: forall a e. (Exception e) => (e -> IO a) -> Handler a --sigbjorn

On Mon, 2008-11-03 at 09:26 -0800, Sigbjorn Finne wrote:
On 11/3/2008 07:34, Jason Dagit wrote:
....
Ah, but I had one more question that I don't think anyone has answered yet. That is, how to deal with multiple types of exceptions. Suppose, as a concrete example, that I was looking out for both ExitCode and PatternMatchFail exceptions. Maybe I'm being naive, but it seems like I'm in that situation again where I have to catch all and then check if fromException succeeds on either PatternMatchFile or ExitCode types. And then throw if it both give Nothing?
One way to do this now is to use Control.Exception.catches:
catches :: IO a -> [Handler a] -> IO a data Handler a where Handler :: forall a e. (Exception e) => (e -> IO a) -> Handler a
ie: action `catches` [ \(e :: ExitCode) -> ... , \(e :: PatternMatchFail) -> ... ] or just by using multiple catch clauses: action `catch` (\(e :: ExitCode) -> ...) `catch` (\(e :: PatternMatchFail) -> ...) Duncan

On Mon, Nov 3, 2008 at 12:53 PM, Duncan Coutts
On Mon, 2008-11-03 at 09:26 -0800, Sigbjorn Finne wrote:
One way to do this now is to use Control.Exception.catches:
catches :: IO a -> [Handler a] -> IO a data Handler a where Handler :: forall a e. (Exception e) => (e -> IO a) -> Handler a
ie:
action `catches` [ \(e :: ExitCode) -> ... , \(e :: PatternMatchFail) -> ... ]
or just by using multiple catch clauses:
action `catch` (\(e :: ExitCode) -> ...) `catch` (\(e :: PatternMatchFail) -> ...)
I don't think those are equivalent. In the second case, the
PatternMatchFail handler scopes over the ExitCode handler.
--
Dave Menendez

On Tue, 04 Nov 2008 07:40:50 +0900, David Menendez
ie:
action `catches` [ \(e :: ExitCode) -> ... , \(e :: PatternMatchFail) -> ... ]
or just by using multiple catch clauses:
action `catch` (\(e :: ExitCode) -> ...) `catch` (\(e :: PatternMatchFail) -> ...)
I don't think those are equivalent. In the second case, the PatternMatchFail handler scopes over the ExitCode handler.
I think Duncan forgot to write parens. According to Ian's example, here is an equivalent code. (action `catch` (\(e :: ExitCode) -> ...)) `catch` (\(e :: PatternMatchFail) -> ...) http://www.haskell.org/pipermail/libraries/2008-July/010095.html Best Regards, -- shelarcy <shelarcy hotmail.co.jp> http://page.freett.com/shelarcy/

On Mon, Nov 3, 2008 at 7:27 PM, shelarcy
On Tue, 04 Nov 2008 07:40:50 +0900, David Menendez
wrote: ie:
action `catches` [ \(e :: ExitCode) -> ... , \(e :: PatternMatchFail) -> ... ]
or just by using multiple catch clauses:
action `catch` (\(e :: ExitCode) -> ...) `catch` (\(e :: PatternMatchFail) -> ...)
I don't think those are equivalent. In the second case, the PatternMatchFail handler scopes over the ExitCode handler.
I think Duncan forgot to write parens. According to Ian's example, here is an equivalent code.
(action `catch` (\(e :: ExitCode) -> ...)) `catch` (\(e :: PatternMatchFail) -> ...)
http://www.haskell.org/pipermail/libraries/2008-July/010095.html
That's equivalent to the code without the parentheses, but it isn't
equivalent to the code using "catches".
Assume we have exitCodeHandler :: ExitCode -> IO () and
pattternMatchHandler :: PatternMatchFail -> IO (),
1. action `catches` [ Handler exitCodeHandler, Handler patternMatchHandler ]
2. (action `catch` exitCodeHandler) `catch` patternMatchHandler
Let's further assume that "action" throws an ExitCode exception and
"exitCodeHandler" throws a PatternMatchFail exception. In example 1,
the PatternMatchFail exception thrown by "exitCodeHandler" is not
caught by "patternMatchHandler", but it in example 2 it is caught.
In other words, patternMatchHandler is active during the evaluation of
exitCodeHandler in example 2, but not in example 1.
--
Dave Menendez

Jason Dagit wrote:
On Mon, Nov 3, 2008 at 6:24 AM, Simon Marlow
wrote: Jason Dagit wrote:
Johannes Waldmann wrote:
with 6.10, the following does not typecheck:
foo `Control.Exception.catch` \ _ -> return bar
Ambiguous type variable `e' in the constraint: `Control.Exception.Exception e'
It is probably bad programming style anyway but what is the workaround? As long as you're aware that it is bad programming style. We deliberately didn't include an easy way to do this, because we want people to think about why they need to catch *all* exceptions (most of the time it's a bug). Since the above is bad form, what should I be doing? Could someone
On Wed, Oct 8, 2008 at 1:19 AM, Simon Marlow
wrote: please provide some examples or point me at the list of exceptions that I can catch? What about catching multiple types of exceptions? Let's distinguish two kinds of exception handling: Thanks. This helps a lot. Mind if I put it somewhere, such as on the wiki?
A good description of how to deal with exceptions would be great to have in the Haddock documentation for Control.Exception - would you (or someone else) like to write and submit a patch? Or failing that, just putting it on the wiki would be useful too. Cheers, Simon

On Tue, Nov 4, 2008 at 2:47 AM, Simon Marlow
Jason Dagit wrote:
Thanks. This helps a lot. Mind if I put it somewhere, such as on the wiki?
A good description of how to deal with exceptions would be great to have in the Haddock documentation for Control.Exception - would you (or someone else) like to write and submit a patch? Or failing that, just putting it on the wiki would be useful too.
I don't mind submitting a patch. What is the URL of the repo I should download? Thanks! Jason

Jason Dagit wrote:
On Tue, Nov 4, 2008 at 2:47 AM, Simon Marlow
wrote: Jason Dagit wrote:
Thanks. This helps a lot. Mind if I put it somewhere, such as on the wiki? A good description of how to deal with exceptions would be great to have in the Haddock documentation for Control.Exception - would you (or someone else) like to write and submit a patch? Or failing that, just putting it on the wiki would be useful too.
I don't mind submitting a patch. What is the URL of the repo I should download?
http://darcs.haskell.org/packages/base and the file is Control/Exception.hs. Cheers, Simon
participants (9)
-
Antoine Latter
-
David Menendez
-
Duncan Coutts
-
Jason Dagit
-
Johannes Waldmann
-
shelarcy
-
Sigbjorn Finne
-
Simon Marlow
-
Thomas Schilling