
Hi, All. I am trying to understand the new exceptions package in base-4 Control.Exceptions. The documentation for catchJust is the same as in Control.OldException including this example: result <- catchJust errorCalls thing_to_try handler Control.OldException provides the predicate errorCalls, but the new one does not. I don't see how to write it. Thanks for reading. Cheers, David

I think catch is now basically what catchJust was -- you can just do
thing_to_try `catch` (\ (ErrorCall s) -> putStrLn s)
and it will only catch ErrorCall exceptions. -Ross David F. Place wrote:
Hi, All.
I am trying to understand the new exceptions package in base-4 Control.Exceptions. The documentation for catchJust is the same as in Control.OldException including this example:
result <- catchJust errorCalls thing_to_try handler
Control.OldException provides the predicate errorCalls, but the new one does not. I don't see how to write it.
Thanks for reading.
Cheers, David
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Be careful, though. This only works if there's a single constructor
for your exception type. If there are multiple, you should write it
like this:
thing_to_try `catch` \(e :: MyErrorType) -> case e of MyError1 _ ->
..; MyError2 _ -> ...
If you write `catch` (MyError1 ...) and a MyError2 is thrown, you will
get a pattern match error exception.
If you want to catch multiple exceptions (of different type) at once,
use the "catches" combinator.
2008/11/22 Ross Mellgren
I think catch is now basically what catchJust was -- you can just do
thing_to_try `catch` (\ (ErrorCall s) -> putStrLn s)
and it will only catch ErrorCall exceptions.
-Ross
David F. Place wrote:
Hi, All.
I am trying to understand the new exceptions package in base-4 Control.Exceptions. The documentation for catchJust is the same as in Control.OldException including this example:
result <- catchJust errorCalls thing_to_try handler
Control.OldException provides the predicate errorCalls, but the new one does not. I don't see how to write it.
Thanks for reading.
Cheers, David
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Push the envelope. Watch it bend.

On Sat, 2008-11-22 at 11:33 +0000, Thomas Schilling wrote:
Be careful, though. This only works if there's a single constructor for your exception type. If there are multiple, you should write it like this:
thing_to_try `catch` \(e :: MyErrorType) -> case e of MyError1 _ -> ..; MyError2 _ -> ...
If you write `catch` (MyError1 ...) and a MyError2 is thrown, you will get a pattern match error exception.
Since I am trying to replicate the behavior of errorCalls, I have only the single constructor ErrorCall to worry about. I don't understand though, how this works: I have a predicate errorCalls e@(ErrorCall _) = Just e In the following transcript it seems to work correctly even if something beside ErrorCall is thrown. Passing NonTermination to errorCalls get a type error as expected. Why does it work inside tryJust? *Main> tryJust errorCalls $ print $ [] !! 23 tryJust errorCalls $ print $ [] !! 23^JLeft Prelude.(!!): index too large *Main> tryJust errorCalls $ print $ throw NonTermination tryJust errorCalls $ print $ throw NonTermination^J*** Exception: <<loop>> *Main> errorCalls (ErrorCall "What?") errorCalls (ErrorCall "What?")^JJust What? *Main> errorCalls NonTermination errorCalls NonTermination^J <interactive>:1:11: Couldn't match expected type `ErrorCall' against inferred type `NonTermination' In the first argument of `errorCalls', namely `NonTermination' In the expression: errorCalls NonTermination In the definition of `it': it = errorCalls NonTermination

2008/11/22 David F. Place
On Sat, 2008-11-22 at 11:33 +0000, Thomas Schilling wrote:
Be careful, though. This only works if there's a single constructor for your exception type. If there are multiple, you should write it like this:
thing_to_try `catch` \(e :: MyErrorType) -> case e of MyError1 _ -> ..; MyError2 _ -> ...
If you write `catch` (MyError1 ...) and a MyError2 is thrown, you will get a pattern match error exception.
Since I am trying to replicate the behavior of errorCalls, I have only the single constructor ErrorCall to worry about. I don't understand though, how this works: I have a predicate
errorCalls e@(ErrorCall _) = Just e
In the following transcript it seems to work correctly even if something beside ErrorCall is thrown. Passing NonTermination to errorCalls get a type error as expected. Why does it work inside tryJust?
*Main> tryJust errorCalls $ print $ [] !! 23 tryJust errorCalls $ print $ [] !! 23^JLeft Prelude.(!!): index too large
*Main> tryJust errorCalls $ print $ throw NonTermination tryJust errorCalls $ print $ throw NonTermination^J*** Exception: <<loop>>
It doesn't. The last line is printed by GHCi. Note the missing "Exception: " in the first call.

On Sat, 2008-11-22 at 15:27 +0000, Thomas Schilling wrote:
*Main> tryJust errorCalls $ print $ [] !! 23 tryJust errorCalls $ print $ [] !! 23^JLeft Prelude.(!!):
index
too large
*Main> tryJust errorCalls $ print $ throw NonTermination tryJust errorCalls $ print $ throw NonTermination^J*** Exception: <<loop>>
It doesn't. The last line is printed by GHCi.
Note the missing "Exception: " in the first call.
!! uses error, so the first call shouldn't have "Exception: ." It is handled by tryJust and not rethrown.

On Sat, 22 Nov 2008, Thomas Schilling wrote:
Be careful, though. This only works if there's a single constructor for your exception type. If there are multiple, you should write it like this:
thing_to_try `catch` \(e :: MyErrorType) -> case e of MyError1 _ -> ..; MyError2 _ -> ...
If you write `catch` (MyError1 ...) and a MyError2 is thrown, you will get a pattern match error exception.
A "pattern match exception" or "pattern match error"? I mean, not handling a certain pattern is a programming error not an exceptional condition at runtime. Thus there is no need to throw a "pattern match exception" which is catched and handled somewhere else.

It's a pattern match error, implemented by throwing an asynchronous
exception. The idea being, that we only have one mechanism (well, an
synchronous exceptions, thrown via throwIO).
Yes, I know that there's a difference between "error" and "exception",
but I would argue that which is which depends on the program. For
example, for most programs a pattern match error is a fatal condition,
there's no sane recovery from it. OTOH, in a program like GHCi, a
pattern match error in an executed statement is an exceptional
condition, which we want to catch, so it doesn't kill GHCi.
2008/11/22 Henning Thielemann
On Sat, 22 Nov 2008, Thomas Schilling wrote:
Be careful, though. This only works if there's a single constructor for your exception type. If there are multiple, you should write it like this:
thing_to_try `catch` \(e :: MyErrorType) -> case e of MyError1 _ -> ..; MyError2 _ -> ...
If you write `catch` (MyError1 ...) and a MyError2 is thrown, you will get a pattern match error exception.
A "pattern match exception" or "pattern match error"? I mean, not handling a certain pattern is a programming error not an exceptional condition at runtime. Thus there is no need to throw a "pattern match exception" which is catched and handled somewhere else.
-- Push the envelope. Watch it bend.

On Sat, 22 Nov 2008, Thomas Schilling wrote:
It's a pattern match error, implemented by throwing an asynchronous exception. The idea being, that we only have one mechanism (well, an synchronous exceptions, thrown via throwIO).
Yes, I know that there's a difference between "error" and "exception", but I would argue that which is which depends on the program. For example, for most programs a pattern match error is a fatal condition, there's no sane recovery from it. OTOH, in a program like GHCi, a pattern match error in an executed statement is an exceptional condition, which we want to catch, so it doesn't kill GHCi.
It's completely ok to run something in a sandbox and try to observe errors. But that's debugging and I think there is no need to do this in many places of an application. In general handling errors automatically is not possible, because an error might also be if a program loops infinitely. Thus one should not generally handle an error like an exception.

On Sun, 2008-11-23 at 01:40 +0100, Henning Thielemann wrote:
On Sat, 22 Nov 2008, Thomas Schilling wrote:
It's a pattern match error, implemented by throwing an asynchronous exception. The idea being, that we only have one mechanism (well, an synchronous exceptions, thrown via throwIO).
Yes, I know that there's a difference between "error" and "exception", but I would argue that which is which depends on the program. For example, for most programs a pattern match error is a fatal condition, there's no sane recovery from it. OTOH, in a program like GHCi, a pattern match error in an executed statement is an exceptional condition, which we want to catch, so it doesn't kill GHCi.
It's completely ok to run something in a sandbox and try to observe errors. But that's debugging and I think there is no need to do this in many places of an application. In general handling errors automatically is not possible, because an error might also be if a program loops infinitely. Thus one should not generally handle an error like an exception.
In general I agree. I would advise against explicitly catching such exceptions just in the region where one is expecting them. That seems like bad design. On the other hand "top level" catch-all handlers that also catch such logic errors sometimes make sense. For example in a Haskell web server where we generate a page dynamically it makes a lot of sense to catch errors in the page-generation function, including pattern match errors, and produce a 500 error code response and log the error message. That's a case, rather like ghci, where some flaw in the program can and should be compartmentalised. There's no attempt to clean up the error but it is a modular system and there is a clear boundary where failures can occur without bringing down the entire system. Duncan

On Sun, 23 Nov 2008, Duncan Coutts wrote:
On Sun, 2008-11-23 at 01:40 +0100, Henning Thielemann wrote:
On Sat, 22 Nov 2008, Thomas Schilling wrote:
It's a pattern match error, implemented by throwing an asynchronous exception. The idea being, that we only have one mechanism (well, an synchronous exceptions, thrown via throwIO).
Yes, I know that there's a difference between "error" and "exception", but I would argue that which is which depends on the program. For example, for most programs a pattern match error is a fatal condition, there's no sane recovery from it. OTOH, in a program like GHCi, a pattern match error in an executed statement is an exceptional condition, which we want to catch, so it doesn't kill GHCi.
It's completely ok to run something in a sandbox and try to observe errors. But that's debugging and I think there is no need to do this in many places of an application. In general handling errors automatically is not possible, because an error might also be if a program loops infinitely. Thus one should not generally handle an error like an exception.
In general I agree. I would advise against explicitly catching such exceptions just in the region where one is expecting them. That seems like bad design.
On the other hand "top level" catch-all handlers that also catch such logic errors sometimes make sense. For example in a Haskell web server where we generate a page dynamically it makes a lot of sense to catch errors in the page-generation function, including pattern match errors, and produce a 500 error code response and log the error message.
That's a case, rather like ghci, where some flaw in the program can and should be compartmentalised. There's no attempt to clean up the error but it is a modular system and there is a clear boundary where failures can occur without bringing down the entire system.
full acknowledge

BTW, the documentation of catch is bad: the example catch (openFile f ReadMode) (\e -> hPutStr stderr ("Couldn't open "++f++": " ++ show e)) does not type check. Is this a known "bug" or shall I report it anywhere? Regards, Martin. Ross Mellgren schrieb:
I think catch is now basically what catchJust was -- you can just do
thing_to_try `catch` (\ (ErrorCall s) -> putStrLn s)
and it will only catch ErrorCall exceptions.
-Ross
David F. Place wrote:
Hi, All.
I am trying to understand the new exceptions package in base-4 Control.Exceptions. The documentation for catchJust is the same as in Control.OldException including this example:
result <- catchJust errorCalls thing_to_try handler
Control.OldException provides the predicate errorCalls, but the new one does not. I don't see how to write it.
Thanks for reading.
Cheers, David
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (6)
-
David F. Place
-
Duncan Coutts
-
Henning Thielemann
-
Martin Huschenbett
-
Ross Mellgren
-
Thomas Schilling