[Haskell-cafe] Re: hGetContents and lazyness

Micah Cowan micah at cowan.name
Tue Sep 23 12:55:15 EDT 2008

Hash: SHA1

Max Vasin wrote:
> Micah Cowan <micah at cowan.name> writes:
>> I think we'd need to see the actual input and expected output, to
>> understand what's going wrong here. It worked fine for me, for small tests.
> The gzipped example file is here:
> ftp://ftp.debian.org/debian/dists/lenny/contrib/binary-i386/Packages.gz
>> By the way, it's good policy to always post complete, runnable examples.
>> Requiring anyone who wants to help you to write additional code just to
>> get it to run decreases the chances that someone will bother to do so.
> Sorry. I've just omitted module imports:
>> import Control.Monad (filterM, mapM)
>> import System.IO (withFile, IOMode (ReadMode), hGetContents)
>> import qualified System.Posix.Files as SPF (isDirectory, getFileStatus)

Actually, I meant more the missing "main" function; but the example
invocation you gave will do fine.

As previously mentioned, the full list will be output if you ensure that
the putStrLn calls take place within withFile, rather than without:

getPackageList :: FilePath -> IO ()
getPackageList packageFile = withFile packageFile ReadMode $
         \h -> do c <- hGetContents h
         mapM_ (putStrLn . drop 10) $
             filter (startsWith "Filename:") $ lines c
    where startsWith [] _ = True
          startsWith _ [] = False
          startsWith (x:xs) (y:ys) | x == y    = startsWith xs ys
                                   | otherwise = False

Your experiments with $! don't work, I believe because seq only does a
"shallow" evaluation: in particular, it doesn't evaluate successive
elements in a list (RWH puts it: "seq stops as soon as it reaches a
constructor" ($! is defined in terms of seq)). In order to work around
this, you'd need to define your own versions of map and filter to manage
the construction using seq. Not worth it, IMO, especially since
accomplishing this forces the whole list to be held in memory, which
isn't as nice as processing things sequentially before the file has been

- --
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer.
GNU Maintainer: wget, screen, teseq
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org


More information about the Haskell-Cafe mailing list