
On Fri, Oct 19, 2007 at 02:09:01 +1000, Matthew Brecknell wrote:
Magnus Therning:
Just out of curiosity, how would I go about finding this myself? (Ideally it'd be an answer other than "read the source for the libraries you are using". :-)
Well, I can at least try to expand a little on "read the source". :-)
You'll first need a solid understanding of lazy evaluation in the context of pure computations. Read about normal evaluation order, WHNF (weak head normal form), and which contexts force WHNF. Use pen and paper to manually derive the evaluation order for some pure computations of your choice (folds over infinite lists would be a good start). Experiment with "seq". Experiment with the various causes of stack overflows. Next, understand that while the IO monad is quite strict about sequencing actions, its "return" is not strict in its argument. Observe that the combinators in Control.Monad generally do not force returned computations. Browse the source of GHC's IO library to understand how it sequences IO actions. Read the source for unsafePerformIO and unsafeInterleaveIO to understand how and for what purposes they allow you to break that sequencing. Next, read the source for hGetContents. After all that, you should be a little better equipped to diagnose problems with lazy IO!
I'll certainly try to look into all of that. However, I suspect your suggestion doesn't scale very well. On my original code it's easy, it was less than 10 lines, but how do I know where to start looking if it's a program of 100 lines, or 1000 lines? The problem could occur in an updated library that I just use... Well you get the idea :-) I can use profiling to find where time and space is spent. But what about other finite resources that my program uses, such as file handles? /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus@therning.org Jabber: magnus.therning@gmail.com http://therning.org/magnus