[Haskell-cafe] Flattening tail recursion?
Daniel Fischer
daniel.is.fischer at web.de
Mon Dec 13 05:56:45 EST 2004
Hi everyone,
I had the idea that, instead of using 'seq', one might check for parity:
countLines2 aux (_:l)
| even aux = ...
| odd aux = ...
that prevents stack overflow, but is much slower than
countLines1 aux (_:l)
| aux `seq` False = ...
| otherwise = ...
I also tried
countLines3 aux (_:l)
| even aux || odd aux = ...
| otherwise = ...
and
countLines4 aux (_:l)
| even aux || True = ...
| otherwise = ...
which also are slower than countLines1.
Well, checking for parity takes time, so that is no real surprise.
What somehow puzzles me is that, compiling with -O, all versions of countLines
are equally fast, if I give the type
countLines :: Int -> [a] -> Int,
but if I replace Int with Integer, the plain version without guards and the
'seq' version are equally fast whereas the parity-check versions are equally
fast among themselves but slower than plain.
If I omit the type-declaration, all versions perform differently, plain
producing stack overflow, countLines1 being by far the fastest, countLines4
coming in second, then countLines3 and last countLines2.
If I give the type Int -> [a] -> Int and use interpreted code, plain
overflows, countLines1 is by far the fastest, but then things change. Now
countLines2 comes in second, third is countLines4, relatively close, last, at
a distance, is countLines3. (Qualitatively the same, but slower, without
type-declaration).
With type Int -> [a] -> Int, but compiled without -O, the results are (for
countLinesX 0 [1 .. 1500000])
plain : stack overflow,
1 : 0.43 secs,
2 : 1.10 secs,
3 : 1.26 secs,
4 : 0.93 secs.
Now obviously -O does a good job (though 'seq' isn't so bad even without -O),
but why does checking for parity take extra time for Integer and not for Int?
And why does compilation without -O change the order of versions 2-4 ?
If anybody knows, mind telling me?
Thanks in advance,
Daniel
Am Freitag, 10. Dezember 2004 22:37 schrieb Jules Bean:
> On 10 Dec 2004, at 20:33, GoldPython wrote:
> > Just compiled this with -O and it ran with no stack overflow.
> > Evidently, no `seq` needed for this one. Using ghc 6.2.2.
> >
> > countLines l = countLines' 0 l
> > countLines' n [] = n
> > countLines' n (_:ls) = countLines' (n + 1) ls
>
> That's presumably the answer. GHC's strictness analyser *can* cope with
> this situation but only under -O... whereas most of us where testing
> under ghci...
>
> Confirmation from one of the Simons?
>
> Jules
>
> _______________________________________________
> 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