[Haskell-cafe] IO and lazyness.

Jeremy Shaw jeremy.shaw at linspireinc.com
Tue Mar 6 14:12:04 EST 2007


Hello,

There are a few solutions, depending on what behaviour you want. If
you plan to read the file all the way to the end, then you do not need
to explicitly close the handle, hGetContents will do it for you.

http://www.haskell.org/ghc/docs/latest/html/libraries/base/System-IO.html#v%3AhGetContents

If you plan to read only a portion of the file, (ie, only read enough
to find the first occurance of a key), then you have to make sure you
have really forced the 'rechf2' to do its work before hClose is
called.

'print' works, because it forces the value to be printed. You can also
force the value by using seq or evaluate. Instead of 'print f' you
could do something like:

	evaluate $ length f

This forces all of 'f' to be read in.  (This would also trigger
hGetContents to close the file, so you still would not need
hClose). However, if f is very large, then you may not want it to be
read into memory all at once.

So, instead you might change the last line of rechf2 to:

  return $! rech r $ lines f

This should make the return value strict. Since you would not have to
read the whole file in this case, you would need to keep your explicit
hClose.

j.

ps. I didn't actually try any of these suggestions, so I may be wrong.

pps. depending on your needs, you might also just opt to use readFile
instead of hGetContents


At Tue, 6 Mar 2007 19:37:38 +0100,
D.V. wrote:
> 
> Hello,
> 
> I'm still learning Haskell and I am stuck on a probably simple problem.
> 
> Assume I have a file where lines are of the form "key=value"
> 
> I want to search a value in that file and came up with the following code.
> 
> > rechf :: String -> IO (Maybe String)
> > rechf r = bracket (openFile "liste" ReadMode)
>                   (hClose)
>                   (rechf2 r)
> >
> > rechf2 :: String -> Handle -> IO (Maybe String)
> > rechf2 r h= do
> >   f <- hGetContents h
> >   --print f
> >   return $ rech r $ lines f
> >
> > rech :: String -> [ String ] -> Maybe String
> > rech r l = lookup r $ map span2 l
> >
> > span2 :: String->(String,String)
> > span2 c = (a,b)
> >   where a=takeWhile (/='=') c
> >         b=drop 1 $ dropWhile (/='=') c
> 
> Now the problem is this :
> 1) if I try rechf, it returns nothing even for a key that exists in the file.
> 2) if I uncomment the line where there is "print f", the key is found
> and the value returned.
> 
> I'm guessing print forces f to be evaluated, so the file is actually
> read, but I was wondering why it doesn't work without it and how to
> correct that.
> 
> David.
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe


More information about the Haskell-Cafe mailing list