Lazy streams and unsafeInterleaveIO
Tue, 24 Dec 2002 01:25:14 -0800
Glynn Clements wrote:
>>So is this lazy-stream-via-unsafeInterleaveIO not so nasty, then, so
>>long as a few precautions (not reading too far into the stream,
>>accounting for buffering, etc.) are taken? I like the idiom Hudak uses
>>(passing a stream of I/O results to the purely functional part of the
>>program), so if it's kosher enough I'd like to get hacking elsewhere ...
>It depends upon the amount and the complexity of the program's I/O,
>and the degree of control which you require. For a simple stream
>filter (read stdin, write stdout), lazy I/O is fine; for a program
>which has more complex I/O behaviour, lazy I/O may become a nuisance
>as the program grows more complex or as you need finer control.
>If you just wanted a getContents replacement with a prompt, the
>obvious solution would be to use unsafeInterleaveIO just to implement
>that specific function.
Well, yeah - but I don't want to get into the habit of using the
unsafe*IO stuff when it just seems convenient. This way, I know
specifically why I need it, and can encapsulate its use in a small
library with predictable results (i.e. I can separate concerns).
>The main problems with lazy I/O are the lack of control over ordering
>(e.g. you can't delete the file until a stream has been closed, but
>you may not be able to control how long the stream remains open) [...]
Wait ... but the Library Report (11.2.1) says that, after a call to
hGetContents (which I assume getContents is based on), the file is
"semi-closed," and a call to hClose will indeed then close it ...
>the inability to handle exceptions (the actual exception won't occur
>until after e.g. getContents has returned).
But how does this differ from strict I/O? I mean, say there's a disk
error in the middle of some big file I want to crunch. Under traditional
I/O, I open the file and proceed to read each piece of data, process it,
and continue to the next one, reading the raw data only as I need it.
When I hit the error, an exception will be thrown in the middle of the
operation. In lazy I/O, I might use getContents to get all the
characters lazily; the getContents call will read each piece of data as
it's needed in the operation - in other words, the data is read as the
program uses it, just like with traditional I/O. And when the error
occurs, the operation will be unceremoniously interrupted, again the
same as by strict I/O. In mean, if an exception is thrown because of a
file error, I can't hope to catch it in the data-crunching part of the
program anyway ...