seq / strictness and laziness

Dean Herington heringto@cs.unc.edu
Mon, 12 Nov 2001 11:05:55 -0500


`seq` forces evaluation of only the top-level construct in its first
argument.  (($!) similarly for its second argument.)  I would guess your
"newcounts" are structured (probably a tuple or list), in which case you are
not forcing evaluation deeply enough.  See
http://haskell.org/pipermail/haskell/2001-August/001581.html and followup
article.

Dean Herington


Amanda Clare wrote:

> I have some code which is being unnecessarily lazy (and occupying too
> much heap space). The code should read and process several files one by
> one. What's happening is that all files get read in but the processing
> is delayed by laziness, and the files are being retained. It looks
> something like this (after simplification):
>
> main = do
>           result <- foldM countAFile initialcounts fileNameList
>           prettyprint result
>
> countAFile oldcounts filename =
>     do
>         compiledFile <- readAndCompile filename
>         let newcounts = countAssociations compiledFile oldcounts
>         return newcounts
>
> I would love to have used CPS, but this seems to force me to lift a huge
> amount of code into both the IO monad and the CPS, as countAssociations
> just calls another function, which calls another, and so on.
>
> If I change countAFile to use a redundant test to force evaluation of
> newcounts:
>
> countAFile oldcounts filename =
>     do
>         compiledFile <- readAndCompile filename
>         let newcounts = countAssociations compiledFile oldcounts
>         if newcounts == newcounts
>            then return newcounts
>            else error "suitable error message"
>
> then the program runs beautifully (if a little slowly), occupying a
> constant amount of heap.
>
> If instead I use a strict data type to store my counts, or use seq, then
> I get no improvement, and it's just as if I hadn't used them. I
> understand why a strict data type won't help me, as it's the function
> calls that are lazy. But what about $! and seq?
>
> countAFile oldcounts filename =
>     do
>         compiledFile <- readAndCompile filename
>         let newcounts = countAssociations compiledFile oldcounts
>         return $! newcounts
>
> Does anyone understand why $! (or equivalently "seq") have no effect
> here? Is there a better way to do this?
>
> Amanda
> --
> Amanda Clare  http://users.aber.ac.uk/ajc99/
> Tel: +44 (0)1970 621922  Fax: +44 (0)1970 622455
> Dept. of Computer Science, University of Wales, Aberystwyth, SY23 3DB
>
> _______________________________________________
> Haskell mailing list
> Haskell@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell