
- when I'm at a break point, I'd really like to see the current scope or, if that is too expensive, the next enclosing scope, in full (not only would that tell me what instantiation of my code I'm in, it would also seem necessary if I want to reconstruct what the current expression is)
I don't understand what you mean here - surely in order to "reconstruct what the current expression is" you only need to know the values of the free variables of that expression? Also I don't understand what you mean by the "next enclosing scope". Could you give an example?
If <expr> is the current expression f a b = <expr> -- 'a' and 'b' should be inspectable, independent of <expr> g x y = <expr> where a = .. -- 'a' should be inspectable (ideally, 'x'/'y', too)
I don't know what "partially defined value form" is. The debugger shows the source code as... source code!
:list shows source code (without substitution) :print shows partially defined values (partially defined value form, with thunks) :force tries to evaluate, replacing uninspectable thunks with values There is no way to see source with substituted variables, or unevaluated expressions. So there's an information gap between source and values. It is in this gap that many of the interesting/buggy reductions happen (at least in my code;-).
I think I know what you mean though. You want the debugger to substitute the values of free variables in the source code, do some reductions, and show you the result. Unfortunately this is quite hard to implement in GHCi (but I agree it might be useful), because GHCi is not a source-level interpreter.
Yes, that is what I've been missing ever since I moved from my previous functional language to Haskell. But I agree that it would be hard to add as an afterthought. I have high hopes that the GHCi debugger + scope might go most of the way in terms of practical needs. I really think the GHCi debugger is a great step in the right direction, but without being able to inspect the context of the current expression (about which we can only inspect its value, evaluation status, and free variables) it is stuck short of fullfiling its potential. Unless I'm using it wrongly, which is why I was asking.
Currently, I only use the debugger rarely, and almost always have to switch to trace/etc to pin down what it is hinting at. What is the intended usage pattern that makes the debugger more effective/ convenient than trace/etc, and usable without resorting to the latter?
Set a breakpoint on an expression that has the variable you're interested in free, and display its value. If your variable isn't free in the expression you want to set a breakpoint on, then you can add a dummy reference to it.
Adding dummy references means modifying the source, at which point
trace variants do nearly as well. The remaining value of the debugger is
that I can decide at debug time whether or not I want to see the traced
value. Without modifying the source code, there may be no way to step
forward to any expression that has the interesting variables free.
In small examples, it is usually easy to work around the debugger limitations,
so I'll have to remember to make a note next time I encounter the issues
in real life debugging. However, even in small examples, one can see hints
of the issues. Consider this code and session:
f x y z | x