In the current exercise assignment of the Functional Programming course I'm doing, we've got to make a memoized version of a given function. To explain memoization, the following example is given:
fiblist = [ fibm x | x <- [0..]]
fibm 0 = 0
fibm 1 = 1
fibm n = fiblist !! (n-1) + fiblist !! (n-2)
But I don't fully understand how this works.
Let's call fibm 3
.
fibm 3
--> fiblist !! 2 + fibList 1
--> [fibm 0, fibm 1, fibm 2] !! 2 + [fibm 0, fibm 1] !! 1
--> fibm 2 + fibm 1
--> (fiblist !! 1 + fiblist 0) + 1
--> ([fibm 0, fibm 1] !! 1 + [fibm 0] !! 0) + 1
--> (fibm 1 + fibm 0) + 1
--> 1 + 0 + 1
--> 2
From other questions/answers and googling I learned that somehow, the evaluated fiblist is shared between calls.
Does this mean that, for example, for fiblist !! 2 + fiblist !! 1
, the list values are only calculated once for fiblist !! 2
and then just reused for fiblist !! 1
?
Then the two fibonacci numbers are calculated only once per call, so no exponential number of calls. But what about the "lower" levels of the call in the fiblist
function? How do they benefit from the calculated fiblist
in the original fibm
call?