Hacker News new | ask | show | jobs
by gizmo686 4700 days ago
Have you looked into Debug.trace? The type of trace is "String -> a -> a". This is a 'pure' function that 'ignores' the first argument and returns the second unmodified. What actually happens is that the first argument is a String that gets printed to stdout. Furthermore, once you give it the first argument, it is simply the identity function, which allows you to easily place it anywhere in you code.

For example, if you have a function: add x y = x+y, and you wanted to see all of the inputs add gets, you could do: add x y = trace (show (x,y)) $ x+y.

For anyone confused about how such a function is possible in Haskell, not that it is in Debug, and the documentation clearly states that it should only be used for debugging.

EDIT: You could also do traceShow (x,y) $ x+y.

1 comments

I've seen this, it basically allows us to generate execution trace trees, which is quite trivial in most languages must somehow hard in Haskell.

I've studied a lot of mechanisms for debugging Haskell code, and some of the debugging mechanisms taken for granted in other languages can be clawed back. But at the end of the day, it is a struggle: the purity (or more accurately, laziness) that is supposed to help so much ends up hurting in at least one aspect.

Perhaps why Haskell programs are so easy to reason about statically is because they are so hard to reason about dynamically :)

Your last point is the other way around:

Haskell has excellent static reasoning/debugging facilities therefore there is little pressure to make good debugging tools.

I believe purity should make debugging easier, not harder. Laziness should only make performance debugging harder, not correctness debugging.

There is much room for improvement in this space.