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 _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe