I am curious about the runtime performance of an infinite list like the one below:

fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

This will create an infinite list of the fibonacci sequence.

My question is that if I do the following:

takeWhile (<5) fibs

how many times does fibs evaluate each term in the list? It seems that since takeWhile checks the predicate function for each item in the list, the fibs list will evaluate each term multiple times. The first 2 terms are given for free. When takeWhile wants to evaluate (<5) on the 3rd element, we will get:

1 : 1 : zipWith (+) [(1, 1), (1)] => 1 : 1 : 3

Now, once takeWhile wants to evaluate (<5) on the 4th element: the recursive nature of fibs will construct the list again like the following:

1 : 1 : zipWith (+) [(1, 2), (2, 3)] => 1 : 1 : 3 : 5