closing file handles

Tom Pledger Tom.Pledger@peace.com
Mon, 10 Sep 2001 08:44:08 +1200


Hal Daume writes:
 | I'm sorry, I had a small error in my code.  It should have been:
 | 
 | >go filelist = mapM go' filelist          -- no "do return"
 | >    where go' f = do h <- openFile f ReadMode
 | >                     text <- hGetContents h
 | >                     let c = head $! text
 | >                     return (c `seq` (hClose h `seq` c))

Hi.

I don't have a handy installation of ghc to check this on, but here's
a speculative attempt.

    go' f
        = do h    <- openFile f ReadMode
             text <- hGetContents h
             case text of
                 (c:_) -> do hClose h
                             return c

This way, the pattern match on `text' happens before the innermost
`do', which in turn closes the handle before letting the rest of the
computation continue.

You may be able to get a similar effect with one more strictness
operator

    ...
    return $! (c `seq` hClose h `seq` c)

but that's not quite as readable.  BTW I'm not sure that the
strictness operator in `head $! text' makes any difference.  It
ensures that when the expression's evaluated, `text' is reduced to
WHNF before `head' is applied to it.  But then the very next thing
which happens is a pattern match (head (x:_) = x) which would force
that reduction anyway.

Hope that (isn't mistake-ridden and) helps.

- Tom