IO monad and lazy evaluation

Ketil Z. Malde ketil@ii.uib.no
21 May 2003 08:22:02 +0200


Graham Klyne <gk@ninebynine.org> writes:

> showFile fnam =
>      do  { fh <- openFile fnam ReadMode
>          ; fc <- hGetContents fh
>          ; hClose fh
>          ; putStr fc
>          }

> If I load this into Hugs and run it, the output is a single blank line.
> If I reverse the order of hClose and putStr, the source code is displayed.

> I think I can understand why this is happening, but it seems to me
> that there's a violation of referential transparency here: I can't
> see any reasonable justification for the value of 'fc' to vary
> depending on whether it's actually used before or after some other
> I/O operation.

hClose is a strict operation, hGetContents is a lazy one.  You want
hClose to be strict, since the next action may be writing to the same
file; having an unevaluated hGetContents around to be evaluated after
other operations may not give you the result you expect.

For a simple example like the above, use readFile, which reads lazily
and closes the file when it's done.  For complex examples, use handles
with strict IO operations (but be prepared for high memory cost for
those lists of chars)

Perhaps it should be hUnsafeGetContents :-) ?

-kzm
-- 
If I haven't seen further, it is by standing in the footprints of giants