[Haskell-cafe] flushing trace debug output before getting other output

Duncan Coutts duncan.coutts at worc.ox.ac.uk
Sun Jul 17 20:41:08 EDT 2005


On Sun, 2005-07-17 at 04:46 +0000, Terrence Brannon wrote:

> When I remove my various trace statements, I get what I want:
> 
> *Main> printPicture $ superimposeImage imgA imgB
> ................
> ................
> ................
> ................
> ...........##...
> 
> So the question is, how can I leave the trace statements in the code
> and yet get the printPicture output after all the debugging output has
> output? 

Basically you can't. You really shouldn't rely on when the trace output
will happen. The trace 'function' is basically a cheat and you shouldn't
rely on it for anything other than debugging (and even then, it's not
the best debugging aid).

> It only makes sense for it to work that way.

Time to think again I'm afraid! :-)

> The trace output occurs during the program and in particular, during
> the program *prior* to the call to printPicture. Therefore all of the
> trace output should have finished *prior* to printPicture outputting
> it's rows.

Because of lazy evaluation the output gets interleaved with the
computation and the trace output happens during the computation so the
output from both get interleaved. Think of it like this: at each step
it's doing just enough evaluation to figure out the next character to
print, then printing it and then going on to the next step. It is that
"just enough evaluation" bit that is triggering the trace 'function' to
be called and the output to actually happen.

The trace 'function' exposes this (possibly confusing) lazy evaluation
order which most of the time you can be blissfully unaware of. It is for
just this reason (that it'd be horribly confusing) that Haskell does not
allow side effects in functions. And what does trace do? It has side
effects (the console output). This is why I said trace is a 'cheat'. It
is not an ordinary Haskell function and cannot be defined using ordinary
Haskell. Avoid it if you can.

A pragmatic answer to your question is just to note that the trace
output goes to stderr while the ordinary output goes to stdout so you
can redirect the stderr to a seperate file and thereby not see the
interleaving.

./prog 2> stderr.log
cat stderr.log


Duncan



More information about the Haskell-Cafe mailing list