Konrad Hinsen
Thu, 28 Aug 2003 11:33:40 +0200

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=20
(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=20
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 argu=
  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=
an expression for what I want to see, but unless its outcome is required =
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 isolati=
If it takes complex data structures as input, then the only reasonable wa=
y to=20
provide that input may be calling it from another piece of the code. Anot=
problem is that I might not be able to verify the output of a particular=20
function easily, it might take another one to post-process to something=20
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 suitabilit=
y for=20
numerical calculations, where you have to deal with precision and roundin=

> The only tool I've used is HOOD. The version online needs a bit of hack=
> to work with GHC 6 (you need to resolve catch to Control.Exception.catc=
> 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 =
but only type constraints. I found myself having to add "Observable a" to=
type constraints of most of my functions just to be able to add a trace t=
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 =
module. I ended up introducing (minor) bugs into rather unrelated code=20
through typos made when adding "Observable" constraints.