In Haskell, the canonical zipWith implementation of the fibonacci function is :
fibs :: [Integer]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
I have difficulty analysing the time complexity of this (fibs !! n). Trying to write it on paper, at first i thought it was exponential. Then O(n^2) , but I have no clue how it happens to be linear.
Why i think it is linear : https://wiki.haskell.org/The_Fibonacci_sequence#Canonical_zipWith_implementation
Also, i wrote another code :
fibs :: [Integer]
fibs = inc (0,1) where inc (a,b) = a : inc (b,a+b)
This, I believe is clearly O(n). But using the :set +s option in ghci, I see that the zipWith implementation clearly beats mine.
Note: I know that it takes O(n) time for addition of nth and (n-1)th fibonacci number. Thus while testing, i made the base case, i.e. the first two elements 0 : 0 . Time complexities are mentioned using the same assumption.
It would be great if i could get some help with tracing these function calls. I'm interested to know which function was called when and maybe print something to let me know what is going on.
My unsuccessful attempt at this :
zipWith' = trace ("Called zipWith") (zipWith)
add' a b = trace (show a ++ " + " ++ (show b)) (add a b)
fibs = trace ("Called fibs") (1 : 1 : zipWith (+) fibs (tail fibs))
This does not work. The statements are printed exactly one. Except for add' which works fine, surprisingly.
I wish to know how many times and in what order these functions were called.