这主要遵循http://www.haskell.org/haskellwiki/Memoization。
你想要一个 (a -> b) 类型的函数。如果它不调用自己,那么
您可以编写一个简单的包装器来缓存返回值。这
存储此映射的最佳方式取决于您可以使用的 a 的哪些属性
开发。订购几乎是最低限度的。带整数
您可以构造一个无限的惰性列表或保存这些值的树。
type Cacher a b = (a -> b) -> a -> b
positive_list_cacher :: Cacher Int b
positive_list_cacher f n = (map f [0..]) !! n
或
integer_list_cacher :: Cacher Int b
integer_list_cacher f n = (map f (interleave [0..] [-1, -2, ..]) !!
index n where
index n | n < 0 = 2*abs(n) - 1
index n | n >= 0 = 2 * n
所以,假设它是递归的。然后你需要它不调用自己,而是调用
记忆的版本,所以你把它传入:
f_with_memo :: (a -> b) -> a -> b
f_with_memo memoed base = base_answer
f_with_memo memoed arg = calc (memoed (simpler arg))
记忆化的版本当然是我们想要定义的。
但我们可以从创建一个缓存其输入的函数开始:
我们可以通过传入一个创建一个
缓存值的结构。除了我们需要创建 f 的版本
已经有传入的缓存函数。
多亏了懒惰,这没问题:
memoize cacher f = cached where
cached = cacher (f cached)
那么我们只需要使用它:
exposed_f = memoize cacher_for_f f
文章提供了有关如何使用类型类选择的提示
输入到函数来执行上述操作,而不是选择显式
缓存功能。这真的很好——而不是明确地
为输入类型的每个组合构造一个缓存,我们可以隐式地
将类型 a 和 b 的缓存组合成一个用于获取 a 和 b 的函数的缓存。
最后一个警告:使用这种惰性技术意味着缓存永远不会缩小,
它只会增长。如果你改用 IO monad,你可以管理这个,但是
明智的做法取决于使用模式。