On Thu, Jul 12, 2007 at 09:22:09PM -0700, Michael Vanier wrote: > I stumbled across a problem with IO and strictness that I could fix, but I > can't understand why the fix works. I've compressed it down into a program > which simply computes the number of lines in a file. Here is a version > that doesn't work:
snip snip snip > This will return a length of 0 lines for any input file. Obviously, the > "let" is not being evaluated strictly (nor would we expect it to be), so > that when the evaluation is requested, the file is already closed and the > length of the list of lines is 0 (though I might have expected an error). > I then tried this: > > process_file :: FilePath -> IO () > process_file filename = > do h <- openFile filename ReadMode > c <- hGetContents h > let cs = id $! lines c -- try to strictly evaluate the let binding > hClose h > putStrLn $ show $ length cs Calling hClose after hGetContents is the root of the problem, but this is a good example for understanding seq better too. To quote Chris Kuklewicz: > To quote John Meacham: > > | A quick note, > | x `seq` x > | is always exactly equivalant to x. the reason being that your seq > | would never be called to force x unless x was needed anyway. > | > | I only mention it because for some reason this realization did not hit > | me for a long time and once it did a zen-like understanding of seq > | (relative to the random placement and guessing method I had used > | previously) suddenly was bestowed upon me. > > I remember this anecdote because when I first read it, a zen-like > understanding of seq suddenly was bestowed upon /me/. Maybe it should be > in the docs. :-) A little corrallary is (id $!) = id id $! x = x `seq` id x = x `seq` x = x = id x Remember, things defined with let don't get forced when execution in IO goes past that clause in the do block. If want to force something at a particular time between IO actions return $! should work, or Control.Exception.evaluate. I think with return $! strictness analysis might end up evaluating things earlier than you requested, but I haven't found any examples that actually get that to happen. Brandon _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe