[Haskell-cafe] Architecturally flawed
Don Stewart
dons at galois.com
Thu Jul 10 14:41:45 EDT 2008
andrewcoppin:
> I could try GHC's new debugger. But my experiences with it so far have
> shown that for all but the most trivial programs possible, it becomes
> intractably difficult to figure out what the debugger is actually
> showing you. I actually tried to debug a "normal" LZW implementation
> once - one that didn't involve two highly convoluted custom monads and a
> stateful execution model with manually threaded state. This is *not* my
> idea of a fun time...
For what its worth, people are using this at work on large projects
happily.
> In a "normal" programming language, at this point you would sprinkle a
> few print statements around so you can see the intermediate steps the
> program is taking. But I can't. I'm in the wrong monad. Curses!
Use Debug.Trace.trace.
> In the end, the only solution I could come up with was to design a
> second, "hacked" version of the two monads. Instead of importing one
> module, you import another that provides the same interface. However,
> now Reader and Writer are aliases to IO. All write requests cause
> pretty-printed binary to be sent to stdout, and all read requests pop up
> a prompt for input from stdin. It worked reasonably well in that I could
> now add the vitally necessary print statements, and see intermediate
> values and so forth... It wasn't very pretty though.
You should have used Debug.Trace.
> So at least I got that part fixed. Heh. But now I find myself worrying
> about yet *another* problem: is Writer lazy enough?
>
> I mean, the idea is that you can write a program that lazily reads from
> a file, pushes it through a Writer, and lazily writes the result back to
> another file. The thing should chug along reasonably fast and use a
> constant amount of RAM. But all this is only true of Writer is actually
> lazy enough. I have a horrible feeling that all the complicated Origami
> inside makes it too strict. And I have no way to check!
Actually, you can use 'chasingBottoms' to write QuickCheck properties
that state your expected laziness or strictness behaviour.
> Actually, thinking about it, is Reader lazy enough? You call run_reader
> and it hands over your data, but if that data is, say, a list, will
> run_reader build the entire damn list before it'll hand it over? Or will
> the monadic code by called as-needed to generate the list elements?
> Obviously I desire the latter, but I'm really not sure what the actual
> behaviour is...
The mtl Reader class is lazy.
> In summary, I've spent several days coding, and I still don't have a
> single algorithm working. I've spent all my time wrestling with the
> mundane details of infrastructure rather than the interesting algorithms
> I actually set out to implement. This makes me very sad. :-(
You should have stopped by #haskell a few days ago.
> If anybody can think of a better set of abstractions or another way to
> do debugging, I'd be interested to hear about it.
There's already a bit layer for Data.Binary on hackage, for what its
worth. And an LZW encoder/decoder.
> (This would all be so trivial in an OO language. Just make an Encoder
> object that updates its own state internally and talks to a Source
> object and a Destination object for its data...)
Make an Encoder class that updates its own state internally and lazy
streams input and output. As Data.Binary does, as zlib does, et al.
-- Don
More information about the Haskell-Cafe
mailing list