Complexity of two cumulative sum (cumsum) functions in Haskell

Consider the following two cumulative sum (cumsum) functions:

cumsum :: Num a => [a] -> [a]
cumsum [] = []
cumsum [x] = [x]
cumsum (x:y:ys) = x : (cumsum $ (x+y) : ys)

and

cumsum' :: Num a => [a] -> [a]
cumsum' x = [sum $ take k x | k <- [1..length x]]

Of course, I prefer the definition of cumsum to that of cumsum' and I understand that the former has linear complexity.

But just why does cumsum' also have linear complexity? take itself has linear complexity in the length of its argument and k runs from 1 to length x . Therefore I'd have expected quadratic complexity for cumsum' .

Moreover, the constant of cumsum' is lower than that of cumsum . Is that due to the recursive list appending of the latter?

NOTE : welcoming any smart definition of a cumulative sum.

EDIT : I'm measuring execution times using (after enabling :set +s in GHCi):

last $ cumsum [1..n]

This is a measurement error caused by laziness.

Every value in Haskell is lazy: it isn't evaluated until necessary. This includes sub-structure of values - so for example when we see a pattern ( x:xs ) this only forces evaluation of the list far enough to identify that the list is non-empty, but it doesn't force the head x or the tail xs .

The definition of last is something like:

last [x] = x
last (x:xs) = last xs

So when last is applied to the result of cumsum' , it inspects the list comprehension recursively, but only enough to track down the last entry. It doesn't force any of the entries, but it does return the last one.

When this last entry is printed in ghci or whatever, then it is forced which takes linear time as expected. But the other entries are never calculated so we don't see the "expected" quadratic behaviour.

Using maximum instead of last does demonstrate that cumnorm' is quadratic whereas cumnorm is linear.

[Note: this explanation is somewhat hand-wavy: really evaluation is entirely driven by what's needed for the final result, so even last is only evaluted at all because its result is needed. Search for things like "Haskell evaluation order" and "Weak Head Normal Form" to get a more precise explanation.]

链接地址: http://www.djcxy.com/p/40076.html

上一篇: 后缀树和尝试。 有什么不同?

下一篇: Haskell中两个累积和(cumsum)函数的复杂性