GHCi debugger status

Daniil Elovkov daniil.elovkov at googlemail.com
Mon Nov 24 10:02:16 EST 2008


Hello

I think apart from some other notes the concern here, as started by Peter when he joined the thread, can be concisely summarised like this:

it would be good if the set of bound variables were equal to the set of variables syntactically in scope

Apparently, Simon has already explained that that would bear a lot of overhead in the thread "could ghci debugger search for free variables better?" in the end of October - beginning of November.

The reason for that overhead, as I recall the nature of execution in ghc, should be that closures only have pointers to their free variables. Indeed it's only them that is needed for _computing_ the closure. And when we enter a closure we 'forgive' all the outer scope, which is nevertheless syntactically in scope.

I understand the reasons, but I think it's a very serious drawback. I'd love to have a Haskell debugger which is no worse than traditional imperative debuggers, but this seems like a more or less fundamental obstacle.

2 workarounds have been suggested

1. Add references to the identifier of interest in the code, so that it becomes a free variable in the expression where we will stop.

This is hardly compatible with the 'no worse' part.

2. Go back in history to the expression where the identifier of interest is free and thus bound.

For example, in the same October/November thread Peter suggests :tracelocal, which would only record the history of evaluation inside this function. Then, when walking back in history looking for the identifier of interest, one would not get lost in many-many evaluations happening lazily outside of this function and they would not overflow the history slots.

A refinement of :tracelocal could be :tracedirect (or something) that would save the history not anywhere within the given function but only within parents, so to say. For example,

f x y =
   let v = large_exp_v
       w = large_exp_w
   in (w x) + (v y)

If we inspect (v y) then (w x) + (v y) is the parent. In this parent w becomes bound. 
We don't have to record the history for large_exp_v and large_exp_w and we still can get bound all variables which are syntactically in scope.

Also, I think about having a visual debugger (say in Eclipse) that would add value the the ghci debugger. Particularly it could maintain the illusion that all vars in scope and really available, by going back and forth in history.

It could do quite a number of other things as well.

Anyway, even with :tracelocal and :tracedirect the history size limit still can be quite a limitation (yes, tautology). What will happen if we don't limit its size? No memory will ever be released? 



Claus Reinke wrote:
>>> - 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)



More information about the Glasgow-haskell-users mailing list