-- Note: Because of the memoization, both “fibMemo 1” terms refer to the same thunk,

+

-- so it will only be evaluated once.

+

= (fib fibMemo 1 + fibMemo 0) + fibMemo 1

+

= (1 + fibMemo 0) + fibMemo 1

+

= (1 + fib fibMemo 0) + fibMemo 1

+

= (1 + 0) + fibMemo 1

+

= 1 + fibMemo 1

+

-- Remember: “fibMemo 1” was already evaluated, so we can directly replace it by its value.

+

= 1 + 1

+

= 2

+

</haskell>

+

+

As we can see, the whole calculation boils down to the definition of <code>fib</code>, while <code>memoize</code> introduces sharing of thunks.

== Efficient tree data structure for maps from Int to somewhere ==

== Efficient tree data structure for maps from Int to somewhere ==

Line 163:

Line 206:

'''Note: This is migrated from the old wiki.'''

'''Note: This is migrated from the old wiki.'''

−

Memoising constructor functions gives you HashConsing, and you can sometimes use MemoisingCafs to implement that.

+

Memoising constructor functions gives you HashConsing, and you can sometimes use MemoisingCafs ([[constant applicative form]]s) to implement that.

The MemoisingCafs idiom also supports recursion.

The MemoisingCafs idiom also supports recursion.

Line 248:

Line 291:

For instance, one can have finite maps of differing types, but each concrete finite map holds just one type of key and one type of value.

For instance, one can have finite maps of differing types, but each concrete finite map holds just one type of key and one type of value.

−

See the discussion on *Memoizing polymorphic functions*, [http://conal.net/blog/posts/memoizing-polymorphic-functions-part-one/ part one] and [http://conal.net/blog/posts/memoizing-polymorphic-functions-part-two/ part two].

+

See the discussion on ''Memoizing polymorphic functions'', [http://conal.net/blog/posts/memoizing-polymorphic-functions-part-one/ part one] and [http://conal.net/blog/posts/memoizing-polymorphic-functions-part-two/ part two], as well as [http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization/ ''Memoizing polymorphic functions via unmemoization''].

You can just write a memoization function using a data structure that is suitable for your application.
We don't go into the details of this case.
If you want a general solution for several types,
you need a type class, say Memoizable.

memoize :: Memoizable a =>(a->b)->(a->b)

Now, how to implement something like this? Of course, one needs a finite
map that stores values b for keys of type a.
It turns out that such a map can be constructed recursively based on the structure of a:

We can divide the functionality of memoized_fib into the actual calculation and the memoization.
To recombine the functionality, we will use ordinary function composition (.) and the fix point operator fix (cf. Data.Function):

Assuming, fibMemo does indeed calculate the fibonacci numbers, it is a perfect candidate to be plugged into fib.
So, fib fibMemo :: Int -> Integer also calculates the fibonacci numbers, but the first calculation step is done by fib instead of fibMemo itself.
Additionally, memoize is applied to introduce memoization.
Let us look at a small example to make the functionality more clear.

When using this pattern in your own code, note carefully when to call the memoised version (wonderous2 in the above example) and when not to. In general, the partially memoised version (wonderous2' in the above example) should call the memoised version if it needs to perform a recursive call. However, in this instance, we only memoize for small values of x, so the branch of the recursion that passes a larger argument need not bother checking the memo table. (This does slow the array initialization, however.)
Thanks to lazy evaluation, we can even memoise an infinite domain, though we lose constant time lookup. This data structure is O(log N):

What about memoizing polymorphic functions defined with polymorphic recursion?
How can such functions be memoized?
The caching data structures used in memoization typically handle only one type of argument at a time.
For instance, one can have finite maps of differing types, but each concrete finite map holds just one type of key and one type of value.