- 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<y = z
| otherwise = z*y
---------------------
$ /cygdrive/d/fptools/ghc/ghc/stage2-inplace/ghc.exe --interactive Debug.hs
-ignore-dot-ghci
GHCi, version 6.11.20081122: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
[1 of 1] Compiling Main ( Debug.hs, interpreted )
Ok, modules loaded: Main.
*Main> :break f
Breakpoint 0 activated at Debug.hs:(1,0)-(2,24)
*Main> f 3 2 1
Stopped at Debug.hs:(1,0)-(2,24)
_result :: a = _
[Debug.hs:(1,0)-(2,24)] *Main> :list
vv
1 f x y z | x<y = z
2 | otherwise = z*y
^^
3
[Debug.hs:(1,0)-(2,24)] *Main> :step
Stopped at Debug.hs:1:10-12
_result :: a = _
[Debug.hs:1:10-12] *Main> :list
1 f x y z | x<y = z
^^^
2 | otherwise = z*y
[Debug.hs:1:10-12] *Main> :step
Stopped at Debug.hs:2:10-18
_result :: a = _
[Debug.hs:2:10-18] *Main> :list
1 f x y z | x<y = z
2 | otherwise = z*y
^^^^^^^^^
3
[Debug.hs:2:10-18] *Main> :step
Stopped at Debug.hs:2:22-24
_result :: Integer = _
y :: Integer = 2
z :: Integer = _
[Debug.hs:2:22-24] *Main> :list
1 f x y z | x<y = z
2 | otherwise = z*y
^^^
3
[Debug.hs:2:22-24] *Main> :step
2
---------------------
Things to note:
- when reaching the breakpoint "in" 'f', one isn't actually in 'f' yet - nothing
about 'f' can be inspected
- at no point in the session was 'x' inspectable, even though it is likely to
contain information needed to understand 'f', especially when we are
deep in a recursion of a function that can be called from many places;
this information doesn't happen to be needed in the current branch, but
debugging the current expression always happens in a context, and
accessing information about this context is what the GHCi debugger
doesn't seem to support well
In this particular example, the second item is most likely a bug (the free
variables of the guard were never offered for inspection). That is perhaps
more easily shown in the other branch:
---------------------
*Main> f 1 2 3
Stopped at Debug.hs:(1,0)-(2,24)
_result :: a = _
[Debug.hs:(1,0)-(2,24)] *Main> :list
vv
1 f x y z | x<y = z
2 | otherwise = z*y
^^
3
[Debug.hs:(1,0)-(2,24)] *Main> :step
Stopped at Debug.hs:1:10-12
_result :: a = _
[Debug.hs:1:10-12] *Main> :list
1 f x y z | x<y = z
^^^
2 | otherwise = z*y
[Debug.hs:1:10-12] *Main> :step
Stopped at Debug.hs:1:22
_result :: a = _
z :: a = _
[Debug.hs:1:22] *Main> :list
1 f x y z | x<y = z
^
2 | otherwise = z*y
[Debug.hs:1:22] *Main> :step
3
---------------------
Cheers,
Claus
_______________________________________________
Glasgow-haskell-users mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users