
On Thursday 28 August 2003 07:05, Brandon Michael Moore wrote:
What are you trying to debug? I could write something that sounded more relevant if I knew.
The usual kind of problem is getting a wrong result, caused by a typo (misspelled constant, identifier, operator) or a not sufficiently general algorithm. What I would like to be able to do in such cases is trace the evaluation and look at intermediate results. Particular difficulties in Haskell: - Conditional tracing. Suppose a function is called 1000 times but I am interested in a particular intermediate result only when the third argument is greater then three. - Tracing a part of a value, say the first five elements of a list or the even-numbered elements of an array. In both cases the problem seems to be lazy evaluation. I can easily write down an expression for what I want to see, but unless its outcome is required in the computation, it will never be evaluated.
Mostly I try to write my programs in small pieces and check those. It's
Me too, of course. But it isn't always easy to test a function in isolation. If it takes complex data structures as input, then the only reasonable way to provide that input may be calling it from another piece of the code. Another problem is that I might not be able to verify the output of a particular function easily, it might take another one to post-process to something simpler or just something known.
QuickCheck gives a much better indication of correctness with much less manual labor. IIRC I used it when writing a unifier.
I haven't tried QuickCheck yet, but I have my doubts as to its suitability for numerical calculations, where you have to deal with precision and rounding issues.
The only tool I've used is HOOD. The version online needs a bit of hacking to work with GHC 6 (you need to resolve catch to Control.Exception.catch and fix some types). I like the output, and I didn't think the code changes were too bad. I had some trouble defining Observable instances
My problem was that most my code is polymorphic, not specifying concrete types but only type constraints. I found myself having to add "Observable a" to the type constraints of most of my functions just to be able to add a trace to one of them.
the type level). Do you want to avoid ANY code changes?
Not necessarily, but I'd prefer them to be local, at least restricted to one module. I ended up introducing (minor) bugs into rather unrelated code through typos made when adding "Observable" constraints. Konrad.