I was bitten by this a couple of weeks ago.
What I was told back then boils down to the following:
- The proper way to reason about lazy IO is that nothing that doesn't need to be
  read is ever read - in much the same way as the only part of an infinite list that
  gets evaluated is the prefix that you use in your program.
- When reading and writing to the same file, it is better in general to make the
  program transactional by writing to a temp file and then renaming it to the old file.
HTH,
Gesh


On Fri, Mar 15, 2013 at 12:52 AM, Jacek Dudek <jzdudek@gmail.com> wrote:
Q: When trying to compose the following IO actions:

readFile fileName >>= \ contents ->
writeFile fileName (f contents)

I get an exception: openFile: permission denied.
However the following works:

readFile fileName >>= \ contents ->
(mapM_ putStrLn . lines) contents >>
writeFile fileName (f contents)

I'm assuming it has something to do with lazy IO, and the second
action in the second version forces fileName to be read completely and
to be closed.

Why do I need to do that? I thought lazy IO was implemented in such a
way that you were safe to INTERPRET the IO action as having been fully
performed. (And so I would have been safe to interpret that, in the
first version, in the first action, the file was released.)

If that's not the case, then:
(1) What is the proper way to reason about lazy IO?
(2) Is there some action less arbitrary that what I cooked up in the
second version that explicitly instructs to release a file or some
other resource?

Regards, Jacek.

_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://www.haskell.org/mailman/listinfo/beginners