[Haskell-cafe] IO and lazyness.
claus.reinke at talk21.com
Tue Mar 6 17:18:19 EST 2007
> Also, following Jeremy's advice, I replaced the last line of rechf2
> with return $! rech r $ lines f and indeed it works.
> I don't understand why it doesn't without the !
> The documentation for hGetContents says the items are read on demand.
> the function rech needs the strings so they should be read on demand.
> This confuses me :(
that kind of issue comes up frequently, so here is my go at a description. if you
find this helpful, it would be nice if you could put up your questions and answers
on the wiki; if you don't find it helpful, or if the wiki already explains the issues,
please ignore the following.
[I've hereby set up an implicit source of input, which you can read at your own
convenience, as far as you need:-]
hGetContents sets up an implicit computation that will read input on demand for
its output. you're not supposed to do anything else with either the input or the
computation, other than consuming its output, until the demand for the output has
been satisfied completely (and hence the input has been read as far as needed).
openFile/<readsomething>/hClose give you explicit control over the sequence
of file operations. explicit control means you're responsible for organizing things.
either style of i/o works on its own, but don't try to mix them, certainly not on
the same file/handle.
concretely, you're explicitly requesting the file handle to be closed, after the
implicit computation has been set up, but *before* any of its results have been
demanded. that cuts off the input source for the implicit computation. so when
later parts of the program demand its output, there is nothing left to be delivered.
[rechf only returns an access point to the results of the implicit computation]
- move the explicit hClose backwards, until you're sure that you've all the
output you want, and hence are done with the input (sometimes tricky)
- avoid the explict hClose entirely, use only implicit i/o on that file (okay if
you don't need many handles)
- move the demand for the output of the implicit computation forward, to
ensure that its input will be consumed *before* the explicit hClose cuts
it off (involves seq or $! and some forced traversal of the complete
output, eg, via length)
- avoid the implicit hGetContents entirely, use only explicit i/o on that file
(sometimes necessary, but usually more complicated)
[i've hereby explicitly closed the source of input, suggesting there is
nothing more to come]
ps. there should be library functions for getContentsNow/readFileNow,
giving the convenience of implicit i/o without the advantages and pitfalls
of lazy i/o.as long as there aren't, you might find it both instructive and
helpful in practice to define them yourself?
[but then i've added more input here, after the closing; will it be read
implicitly, or ignored explicitly?-]
More information about the Haskell-Cafe