11

I am looking for something to replace loch (and its preprocessor) since it doesn't compile with ghc 7.

Specifically, if error is called then I would like to figure out, as conveniently as possible, where it was called from (line number and stack trace would be nice).

HaskellElephant
  • 9,819
  • 4
  • 38
  • 67
  • You can't really control where or when other libraries use `error`, but my personal preference for my own code is to avoid `error` as much as possible. As general advice to anyone reading this, if you need to know why code is taking a particular branch of execution, *don't* use `error` to find a stack trace; the best way right now is probably `Debug.Trace`. – Dan Burton Dec 21 '11 at 22:02
  • @DanBurton I don't think this applies to what I am asking for. Say that I execute my program and unexpectedly I get `*** Exception: Prelude.head: empty list`, now I would like to know where the call to head that produced this error is in the source code. – HaskellElephant Dec 21 '11 at 22:37
  • I have a patch for ghc that adds that. I need to merge it. – augustss Dec 22 '11 at 00:21
  • @HaskellElephant the solution to *that* would be to avoid functions that you know might throw an exception. It isn't a perfect solution -- there could always be code that you cannot inspect -- but it does solve most issues. – Dan Burton Dec 22 '11 at 02:12
  • Consider using the GHCi debugger. [See my answer here for an example](http://stackoverflow.com/questions/6724434/how-to-debug-haskell-code). – hammar Dec 22 '11 at 16:40

4 Answers4

13

You can use the -xc RTS option, as described on this page; you need to compile your program with profiling support, and the output is pretty ugly, but it works.

This should do it:

$ ghc --make -prof -auto-all myprog.hs
$ ./myprog +RTS -xc

Technically this only gives a cost centre stack, not a true stack trace. Improved stack trace support is coming in GHC 7.4.

ehird
  • 40,602
  • 3
  • 180
  • 182
5

If this is for use in code you're working on, and you can tolerate using Template Haskell, the placeholders package is a cute and simple way to do something like this. It won't help you find the location of actual error expressions, though, only uses of its own error-like functions.

C. A. McCann
  • 76,893
  • 19
  • 209
  • 302
5

It's pretty trivial to get it to build with GHC-7. It's just the Control.Exception change that came with 6.12, the simple fix is to change the Exception type to SomeException in Debug.Trace.Location, line 70 and add an expression type signature in line 144. Restrict the base dependency to >= 4.2 && < 4.6 in the .cabal file (bump the version) and you're good to go.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
3

A quick-n-dirty workaround is the assert function from Control.Exception. However, it's a little clunkier than error.

Warning: All asserts will be silently ignored if you compile with optimizations (ghc -O1, -O2, etc.).

Example:

import Control.Exception

main = do
    print (42 + (assert True  17)) -- adds 42 and 17
    print (42 + (assert False 21)) -- crashes

Output:

59
test.hs: /tmp/test.hs:5:18-23: Assertion failed

Note the line number "5" in the output.

You could use trace from Debug.Trace to add an error message:

    print (42 + (trace "omg error" $ assert False 21))
Geheimdienst
  • 109
  • 1