Question

Is fib evaluated from start for each element of cumfib?

fib = (1:1: zipWith (+) fib (tail fib))
cumfib = [ sum $ take i fib | i<-[1..]]

Or are the first i elements cached and reused for element (i+1) of cumsum?

I am more or less guessing that fib is used in the same lambda expression and hence is is calculated only once.

Furthermore, does the implementation of fib matter regarding how often the i-th Fibonacci number is evaluated? My actual problem concerns prime numbers instead of Fibonacci numbers, which I wish to 'cache' to easily evaluate the prime factors of some number n. However, I only use

takeWhile (\x-> x*x<n) primes 

of the primes. Since I evaluate the factors for small n first and later for bigger n, this subset of primes increases, and hence I wonder, how often is primes evaluated if I do:

primes = ... some way of calculating primes ...
helpHandlePrimes ... = ... using primes ...
handlePrimes = ... using primes and helpHandlePrimes ...

Please let me know whether primes evaluates once, multiple times, or whether this cannot be determined from how I formulated the question.

Was it helpful?

Solution

A let-bound term is usually shared within its scope. In particular, a top-level term in a module is shared in the entire program. However, you have to be careful about the type of the term. If the term is a function, then sharing means that just the lambda abstraction is shared, so the function isn't memoized. An overloaded term is internally represented as a function, and therefore sharing is rather meaningless for an overloaded term as well.

So if you have a monomorphic list of numbers, then it's going to be shared. By default, a list such as fib as you've given will be monomorphic, because of the "monomorphism restriction" (actually here's a case where it's useful). However, these days it's in fashion to disable the monomorphism restriction, so in any case I recommend giving an explicit type signature such as

fib :: [Integer]

to be sure and make it clear to everyone that you're expecting this to be a monomorphic list.

OTHER TIPS

I'd like to add that this way, cumfib needlessly re-computes the sum of first i elements of fib. It can be more efficiently defined as

cumfib = tail $ scanl (+) 0 fib
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top