[Hugs-users] trivial list foldings require quadratic time?
Härmel Nestra
harmel.nestra at ut.ee
Mon Feb 13 13:21:04 EST 2006
Hi,
Recently I noticed that evaluating
minimum [1 .. 10000]
in Hugs takes much more time than evaluating
minimum [10000, 9999 .. 1]
.
This seems weird because evaluating min always needs evaluation of
both its arguments, so the computation schema should be the same.
I think this is a bug.
Making experiments with the length varying leads to the suggestion that
minimum [1 .. n]
runs in quadratic time on n while
minimum [n, n - 1 .. 1]
runs in linear time.
But it would be normal to assume minimum working in linear time in both
cases. By the way, both the number of reductions and the number of cells
reported by Hugs grow linearly in both cases, the corresponding numbers
remain close to each other.
Somehow the reductions of minimum [1 .. 10000] take much more time on an
average then the reductions of minimum [10000, 9999 .. 1] . The difference
is that, in the first case, comparisions are performed with the same element
1 all the time while, in the second case, the numbers being compared
continuously change.
I made yet more experiments. From the expressions
foldl (\ x y -> if x < y then x else y) (maxBound :: Int) [1 .. 10000]
foldl (\ x y -> if x < y then x else y) (maxBound :: Int) [10000, 9999 .. 1]
foldr (\ x y -> if x < y then x else y) (maxBound :: Int) [1 .. 10000]
foldr (\ x y -> if x < y then x else y) (maxBound :: Int) [10000, 9999 .. 1]
the first and the last evaluate slowly while the others evaluate fast,
although evaluation of the last needs by ~20% less reductions and cells than
the third.
The phenomenon occurs even when using foldl' instead of foldl .
The punch-line is that if I modify the expressions as follows:
foldl (\ x y -> if x < y then x + 0 else y + 0) (maxBound :: Int) [1 .. 10000]
foldl (\ x y -> if x < y then x + 0 else y + 0) (maxBound :: Int) [10000, 9999 .. 1]
foldr (\ x y -> if x < y then x + 0 else y + 0) (maxBound :: Int) [1 .. 10000]
foldr (\ x y -> if x < y then x + 0 else y + 0) (maxBound :: Int) [10000, 9999 .. 1]
then all are fast!
The conditional in the operator is not essential:
foldl (\ x y -> x) 0 [1 .. 10000]
evaluates fast,
foldl (\ x y -> ($!) const x y) 0 [1 .. 10000]
evaluates slowly,
foldl (\ x y -> ($!) const (x + 0) y) 0 [1 .. 10000]
evaluates fast again.
All this occurs with both Nov-2003 and Mar-2005 release of Hugs, on both
Linux and Solaris. I have not tested in Windows.
With ghci, this anomaly does not appear.
Härmel
More information about the Hugs-Users
mailing list