[Haskell-cafe] Why does not zipWith' exist
Daniel Fischer
daniel.is.fischer at googlemail.com
Fri Feb 1 13:06:09 CET 2013
On Friday 01 February 2013, 12:50:18, Andres Löh wrote:
> Hi Kazu.
>
> I'd be surprised if zipWith' yields significant improvements. In the
> case of foldl', the strictness affects an internal value (the
> accumulator). However, in the case of zipWith', you're just forcing
> the result a bit more, but I guess the "normal" use pattern of fibs is
> that you want to see a prefix of the result anyway. So the overall
> amount of evaluation is the same.
>
> I've tried to hack up a quick criterion test comparing my own naive
> zipWith, the Prelude zipWith (which may have additional optimizations,
> I haven't checked), and zipWith':
>
> main :: IO ()
> main = defaultMain $ [
> bench "fibs " (nf (take 10000 . fibs ) ())
> , bench "fibsP" (nf (take 10000 . fibsP) ())
> , bench "fibs'" (nf (take 10000 . fibs') ())
> ]
>
> The additional () arguments are to prevent GHC from sharing the list
> in between calls. I haven't tested thoroughly if GHC looks through
> this hack and optimizes it anyway.
>
> Compiling without optimization, I get 1.15ms/1.11ms/1.10ms.
> With -O, I get 85us/85us/88us.
>
> Am I overlooking anything? What's your test?
zipWith' would [I haven't tested, but I'm rather confident] make a difference if
you benchmarked
bench "name" (whnf (fibs !!) 100000)
etc.
The reason is that
foo = initialValues : zipWith f foo (tail foo)
is rather a scan than a real zip, so evaluating an element depends on
evaluating all previous elements, and thus can build a huge thunk if the
elements aren't demanded in order.
For a real zip where an element of the result does not depend on the values of
earlier elements, plain zipWith would perform (usually only marginally) better
than zipWith'.
More information about the Haskell-Cafe
mailing list