seq / strictness and laziness
Amanda Clare
ajc99@aber.ac.uk
Mon, 12 Nov 2001 15:43:08 +0000
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