
so I have found the culprit, by defining this function:
Import Debug.Trace
headMarker :: String -> [a] -> a
headMarker marker [] = trace marker (head [])
headMarker _ array = head array
and replacing calls to head to "headMarker "XX"", "headmarker "YY"" and so
on.
it works but I would really rather have a compiler/runtime based solution
which would not force me to modify my code to track the bug (and would be
simpler to use in case the problem comes from a library).
If anybody has an idea what I did wrong with the -xc and the -RTS I'm all
ears... I'd love to test it and find out how to make that work reliably.
Emmanuel
On Tue, Nov 6, 2012 at 10:50 PM, Emmanuel Touzery
you mean in combination with the RTS/profiling trick? If I must do something like that, I'll just mark my code with debug lines or code the else situations (like making a headMarker with an extra parameter "String marker" and it will output the marker on stdoud if the array is empty), seems less work...
I was really hoping being able to fix it without having the modify the code, it's disappointing, I think.
On Tue, Nov 6, 2012 at 9:47 PM, Christian Maeder
wrote:
Usually, these head calls are in your code. Do "fgrep head" on your sources and replace all suspicious occurrences. Use "let h : _ = l in ..." and "h" instead of "head l" for proper positions.
HTH Christian
Am 06.11.2012 12:44, schrieb Emmanuel Touzery:
Hello,
I'm getting really frustrated by error handling in haskell. By this I mean "assert"-like errors. Which means, something that should never happen, happens. This will happen in the development and deployment of software of any size. When coding the feature you'll say, I don't need to handle the "Nothing" case, because it will never happen, or almost never, and this is not critical production software.
But if one day it happens you find yourself with a several thousand lines program and all you have to debug is the input data (most of the time anyway, sometimes not even that) and this error message (for instance):
*** Exception: Prelude.head: empty list
And you don't know even, did you call "head" or maybe a library you are using called it.
This is really poor compared to what Java, python and others offers. I can understand that it's difficult to provide a stack trace, especially with lazy evaluation, but at least the function name and maybe a line number... Actually I don't know why it would be so difficult to also give me the values of the parameters of the function... using print and if it's a pure function it intuitively doesn't seem difficult.
I've tried ghci with :trace and ":set -fbreak-on-exception" and I got nowhere. It breaks in things which are not important (I have no idea where it breaks, it claims an exception was thrown, maybe but not in my code and it never reaches my code for sure). After hitting ":continue" many times, I get to my exception and there I didn't manage to get useful information (:hist never printed me anything).
But I would like not to have to use ghci at all. And to avoid having to write all over the place in my code these "else" and case situations for things I assume are impossible (these are cases I would not write in other modern languages).
This is a feature for which I would be ready to pay a 50% speed penalty and 50% memory use penalty.
I understand if it's the haskell way of writing all those else clauses... But I think in that case it really makes it compare negatively to other languages. It would be a real minus in my opinion (including to code readability).
I have read (quickly) those but didn't find the solution there: http://www.haskell.org/ghc/**docs/7.0.1/html/users_guide/** ghci-debugger.htmlhttp://www.haskell.org/ghc/docs/7.0.1/html/users_guide/ghci-debugger.html http://book.realworldhaskell.**org/read/error-handling.htmlhttp://book.realworldhaskell.org/read/error-handling.html
Any advice will be welcome! I really hope I missed something.
Emmanuel

Hi Emmanuel! Have you looked at http://hackage.haskell.org/packages/archive/loch-th/0.2.1/doc/html/Debug-Tra... ? With the loch-th package you can write your own head function like this: {-# LANGUAGE TemplateHaskell #-} module Main where import Debug.Trace.LocationTH myHead a = $check $ head a and then something like myHead ([] :: [Char]) will print something like this: test: test.hs:21:12-17: Prelude.head: empty list In docs there is another useful function $failure that is "a location-emitting error call". Hope that helps.

Hello, that is very interesting. on top of that, this library also offers an "assert" function, which will throw an exception with location in the source code if the assert condition is false. so i will definitely consider this. i would really rather compiler support but... That's probably the next best thing. Emmanuel On 7.11.2012 8:51, Karol Samborski wrote:
Hi Emmanuel!
Have you looked at http://hackage.haskell.org/packages/archive/loch-th/0.2.1/doc/html/Debug-Tra... ? With the loch-th package you can write your own head function like this:
{-# LANGUAGE TemplateHaskell #-} module Main where
import Debug.Trace.LocationTH
myHead a = $check $ head a
and then something like myHead ([] :: [Char]) will print something like this: test: test.hs:21:12-17: Prelude.head: empty list
In docs there is another useful function $failure that is "a location-emitting error call".
Hope that helps.

Hi,
On 6 November 2012 22:15, Emmanuel Touzery
If anybody has an idea what I did wrong with the -xc and the -RTS I'm all ears... I'd love to test it and find out how to make that work reliably.
You might want to have a look at the recent emails in ghc-users: (Read Simon Marlow's reply as well) http://www.haskell.org/pipermail/glasgow-haskell-users/2012-November/023029.... HTH, Ozgur

On 6 November 2012 22:15, Emmanuel Touzery
mailto:etouzery@gmail.com> wrote: If anybody has an idea what I did wrong with the -xc and the -RTS I'm all ears... I'd love to test it and find out how to make that work reliably.
You might want to have a look at the recent emails in ghc-users: (Read Simon Marlow's reply as well)
http://www.haskell.org/pipermail/glasgow-haskell-users/2012-November/023029....
reading this makes me think the reason why I got such an unhelpful result with the +RTS -xc might be that I was doing that on the older haskell platform, using GHC 7.0... I may try it now on the latest haskell platform, with GHC 7.4 but who knows, maybe I need GHC 7.6 to get these stack traces reliably, using that -xc trick. emmanuel

On Thu, Nov 08, 2012 at 12:31:09PM +0100, Emmanuel Touzery wrote:
reading this makes me think the reason why I got such an unhelpful result with the +RTS -xc might be that I was doing that on the older haskell platform, using GHC 7.0... I may try it now on the latest haskell platform, with GHC 7.4 but who knows, maybe I need GHC 7.6 to get these stack traces reliably, using that -xc trick.
Looking at the ticket 'http://hackage.haskell.org/trac/ghc/ticket/3693', I don't now if even the current GHC version (7.6.1) is enough to get stack traces. Also the release notes of 7.6.1 don't contain anything about stack traces. I think that stack traces are such a huge thing, that an early 7.6.2 just adding these would be great. Greetings, Daniel

fwiw, I am getting a stack trace with 7.6.1. -- stack.hs main = print $ foo [1] foo xs = bar xs ++ bar xs bar (x:xs) = [x, head xs] $ ghc -prof -auto-all -rtsopts stack.hs $ ./stack +RTS -xc *** Exception (reporting due to +RTS -xc): (THUNK_2_0), stack trace: GHC.List.CAF --> evaluated by: Main.bar, called from Main.foo, called from Main.main, called from Main.CAF --> evaluated by: Main.main, called from Main.CAF stack: Prelude.head: empty list -- Ozgur Akgun

Well I tried and it displays the same with GHC 7.4.1.
However this is the output with GHC 7.0.4:
fwiw, I am getting a stack trace with 7.6.1.
-- stack.hs main = print $ foo [1] foo xs = bar xs ++ bar xs bar (x:xs) = [x, head xs]
$ ghc -prof -auto-all -rtsopts stack.hs
$ ./stack +RTS -xc *** Exception (reporting due to +RTS -xc): (THUNK_2_0), stack trace: GHC.List.CAF --> evaluated by: Main.bar, called from Main.foo, called from Main.main, called from Main.CAF --> evaluated by: Main.main, called from Main.CAF stack: Prelude.head: empty list
-- Ozgur Akgun
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Well I recompiled but now I don't anymore have the input data to reproduce
the problem. However if I hit control-c during the runtime, i get a very
nice, and very big, stack, so i think it would work. So, great! Just be
sure to use ghc 7.4+.
emmanuel
On Thu, Nov 8, 2012 at 6:32 PM, Emmanuel Touzery
Well I tried and it displays the same with GHC 7.4.1.
However this is the output with GHC 7.0.4:
stack: Prelude.head: empty list So this is supported from 7.4 onwards (well maybe 7.2, I guess that version existed).
So there are all the chances that with GHC 7.4.1 I would get a proper stack for my problem. I'll try it soon but I must reinstall all the libraries with profiling on the computer on which I have 7.4.1...
emmanuel
On Thu, Nov 8, 2012 at 1:08 PM, Ozgur Akgun
wrote: fwiw, I am getting a stack trace with 7.6.1.
-- stack.hs main = print $ foo [1] foo xs = bar xs ++ bar xs bar (x:xs) = [x, head xs]
$ ghc -prof -auto-all -rtsopts stack.hs
$ ./stack +RTS -xc *** Exception (reporting due to +RTS -xc): (THUNK_2_0), stack trace: GHC.List.CAF --> evaluated by: Main.bar, called from Main.foo, called from Main.main, called from Main.CAF --> evaluated by: Main.main, called from Main.CAF stack: Prelude.head: empty list
-- Ozgur Akgun
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (4)
-
Daniel Trstenjak
-
Emmanuel Touzery
-
Karol Samborski
-
Ozgur Akgun