
Hello,
I've written a cgi script in haskell, it crashes sometimes with the error
message Prelude . tail : empty list
In Java we would use this approach to log the erro
try {
} catch (Exception e) {
}
--
Pieter Laeremans

Woops , I hit the "send" button to early.
The java approach to locate the error would be
try { ... }catch(Exception e ){
// log error
throw new RuntimeException(e);
}
...
What 's the best equivalent haskell approach ?
thanks in advance,
Pieter
On Tue, Sep 9, 2008 at 10:30 PM, Pieter Laeremans
Hello, I've written a cgi script in haskell, it crashes sometimes with the error message Prelude . tail : empty list
In Java we would use this approach to log the erro
try {
} catch (Exception e) {
}
-- Pieter Laeremans
"The future is here. It's just not evenly distributed yet." W. Gibson
--
Pieter Laeremans

This :
Prelude> let f = (\x -> return "something went wrong") :: IOError -> IO
String
Prelude> let t = return $ show $ "too short list" !! 100 :: IO String
Prelude> catch t f
"*** Exception: Prelude.(!!): index too large
doesn't work.
kind regards,
Pieter
On Tue, Sep 9, 2008 at 10:35 PM, Pieter Laeremans
Woops , I hit the "send" button to early. The java approach to locate the error would be
try { ... }catch(Exception e ){ // log error throw new RuntimeException(e); }
...
What 's the best equivalent haskell approach ?
thanks in advance,
Pieter
On Tue, Sep 9, 2008 at 10:30 PM, Pieter Laeremans
wrote: Hello, I've written a cgi script in haskell, it crashes sometimes with the error message Prelude . tail : empty list
In Java we would use this approach to log the erro
try {
} catch (Exception e) {
}
-- Pieter Laeremans
"The future is here. It's just not evenly distributed yet." W. Gibson
-- Pieter Laeremans
"The future is here. It's just not evenly distributed yet." W. Gibson
--
Pieter Laeremans

On Tue, Sep 09, 2008 at 11:06:43PM +0200, Pieter Laeremans wrote:
This : Prelude> let f = (\x -> return "something went wrong") :: IOError -> IO String Prelude> let t = return $ show $ "too short list" !! 100 :: IO String Prelude> catch t f "*** Exception: Prelude.(!!): index too large
How about:
module Main where
import Control.Exception import Prelude hiding (catch)
f :: Exception -> IO String f = const $ return "sthg went wrong"
g :: String g = show $ "too short list" !! 100
h :: IO String h = do print $ head [0 .. -1] return "huh?"
main = do mapM_ print =<< sequence [ h `catch` f , evaluate g `catch` f , (return $! g) `catch` f , (return g) `catch` f ]
Output: kokr@copper:/tmp$ runhaskell test.lhs "sthg went wrong" "sthg went wrong" "sthg went wrong" "test.lhs: Prelude.(!!): index too large Check documentation of catch and evaluate functions in Control.Exception. Regards, -- Krzysztof Kościuszkiewicz Skype: dr.vee, Gadu: 111851, Jabber: kokr@jabster.pl "Simplicity is the ultimate sophistication" -- Leonardo da Vinci

Pieter Laeremans wrote:
This : Prelude> let f = (\x -> return "something went wrong") :: IOError -> IO String Prelude> let t = return $ show $ "too short list" !! 100 :: IO String Prelude> catch t f "*** Exception: Prelude.(!!): index too large
doesn't work.
As others've said, the right answer is to correct the bug rather than doing exception handling, but in as far as knowing how to do exception handling for "pure" functions, consider: http://code.haskell.org/~wren/wren-extras/Control/Exception/Extras.hs The trickiest thing to watch out for is that you must strictly evaluate the expression or else the return/evaluate function will just lazily thunk up the expression. Which means that when you finally run the IO, you'll have already stripped off the IO wrapper that can catch the exception prior to evaluating the expression (which then throws an exception out past the catcher). Another thing to watch out for is that Prelude.catch doesn't do what you want because the H98 spec declares these exceptions to be uncatchable. The Control.Exception.catch function does what you want and is portable even though it's not H98. If you're doing the unsafePerformIO trick to purify your exception handling be sure to give a NOINLINE pragma to prevent potentially buggy inlining. You should also be sure that the handler is something which is actually safe to unsafePerformIO. Finally, to ensure that other optimizations or evaluation orders don't accidentally mess you up, you should take the higher-order approach of `safely` to ensure that you don't accidentally apply the function prior to wrapping it up in a catcher. -- Live well, ~wren

2008/9/9 Pieter Laeremans
What 's the best equivalent haskell approach ? thanks in advance, Pieter
The preferred approach is to look at your code, figure out where you are using tail (or could be calling something that uses tail) and use the "trace" function to output logging info. Don't forget that output is buffered with trace so you might get some strange ordering. A quick search of the API docs should show you where trace lives. Techniques that worked for Java don't work very well when debugging haskell. Others will tell you about flags and possibly using the debugger but I would count on eyeballing and printing as the least painful method. Justin

"Justin Bailey"
are using tail (or could be calling something that uses tail) and use the "trace" function to output logging info.
Another cheap trick is to use CPP with something like: #define head (\xs -> case xs of { (x:_) -> x ; _ -> error("head failed at line"++__FILE__++show __LINE__)}) -k -- If I haven't seen further, it is by standing in the footprints of giants

Or define your own ghead and gtail: ghead msg [] = error "ghead " ++ msg ++ "[]" ghead _ (x:xs) = x gtail msg [] = error "gtail" ++ msg ++ "[]" gtail msg (x:xs) = xs and you can call them with a name of a function to give you an idea where the error is occurring: myHead = ghead "myHead" [] Chris. On Tue, 9 Sep 2008, Ketil Malde wrote:
"Justin Bailey"
writes: are using tail (or could be calling something that uses tail) and use the "trace" function to output logging info.
Another cheap trick is to use CPP with something like:
#define head (\xs -> case xs of { (x:_) -> x ; _ -> error("head failed at line"++__FILE__++show __LINE__)})
-k

Justin Bailey on 2008-09-09 14:12:38 -0700:
2008/9/9 Pieter Laeremans
: What 's the best equivalent haskell approach ? thanks in advance, Pieter
The preferred approach is to look at your code, figure out where you are using tail (or could be calling something that uses tail) and use the "trace" function to output logging info.
A nice way to automate that is using LocH from Hackage. The original announcement: http://www.haskell.org/pipermail/haskell/2006-November/018729.html

Justin Bailey wrote:
2008/9/9 Pieter Laeremans
: What 's the best equivalent haskell approach ? thanks in advance, Pieter
The preferred approach is to look at your code, figure out where you are using tail (or could be calling something that uses tail) and use the "trace" function to output logging info.
To find the specific tail call: http://haskell.org/ghc/docs/latest/html/users_guide/runtime-control.html#rts... check the description for option -xc Btw, is there any chance ghci debugger would ever print stack. It would be fine to see it in the same way as it exists when executing code ... I'm not interested in the stack as it would look if the program would not be lazy. Peter.

I was going to suggest using the -xc option of the GHC runtime (if you are using GHC), but it seems that it doesn't always give meaningful results as indicated here: http://osdir.com/ml/lang.haskell.glasgow.bugs/2006-09/msg00008.html and here: http://www.haskell.org/pipermail/glasgow-haskell-users/2006-November/011549.... You might want to try it anyway. It's documented in the GHC manual: http://haskell.org/ghc/docs/latest/html/users_guide/runtime-control.html Other than that, there are also haskell debuggers like hat, but I haven't used them myself so I can't really tell if they could help here. Best, Michał On Tue, 2008-09-09 at 22:35 +0200, Pieter Laeremans wrote:
Woops , I hit the "send" button to early.
The java approach to locate the error would be
try { ... }catch(Exception e ){ // log error throw new RuntimeException(e); }
...
What 's the best equivalent haskell approach ?
thanks in advance,
Pieter
On Tue, Sep 9, 2008 at 10:30 PM, Pieter Laeremans
wrote: Hello, I've written a cgi script in haskell, it crashes sometimes with the error message Prelude . tail : empty list
In Java we would use this approach to log the erro
try {
} catch (Exception e) {
}
-- Pieter Laeremans
"The future is here. It's just not evenly distributed yet." W. Gibson
-- Pieter Laeremans
"The future is here. It's just not evenly distributed yet." W. Gibson
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

This : Prelude> let f = (\x -> return "something went wrong") :: IOError -> IO String Prelude> let t = return $ show $ "too short list" !! 100 :: IO String Prelude> catch t f "*** Exception: Prelude.(!!): index too large
doesn't work.
You might be interested in the difference between Prelude.catch and Control.Exception.catch Though in an example like that, you'll need to force evaluation to actually catch the exception. f _ = return "something went wrong" t = return $! show $ "too short list" !! 100 ... Control.Exception.catch t f (note $! instead of $ in "t".) Donn Cave, donn@avvanta.com

Pieter Laeremans wrote:
Hello,
I've written a cgi script in haskell, it crashes sometimes with the error message Prelude . tail : empty list Yup, been there, done that.
First, look for all the uses of "tail" in your program and think hard about all of them. Wrap them in "assert" or "trace" functions to see if there are any clues to be had. Then take a look at the GHC debugger documentation. Debuggers for lazy languages (or indeed any language with closures) is difficult because execution order isn't related to where the faulty data came from. So if I say somewhere x = tail ys and then later on print x the "print" will trigger the error, but the faulty data "ys" may no longer be in scope, so you can't see it.
participants (11)
-
Alec Berryman
-
C.M.Brown
-
Donn Cave
-
Justin Bailey
-
Ketil Malde
-
Krzysztof Kościuszkiewicz
-
Michał Pałka
-
Paul Johnson
-
Peter Hercek
-
Pieter Laeremans
-
wren ng thornton