将记忆添加到递归定义的 haskell 函数
Add memoization to a recursively defined haskell function
我已经解决了 Haskell 中的动态规划问题(实际上是欧拉计划问题),归结为斐波那契数列的推广:
f(n) = f(n-1) + f(n-2)
g(n) = g(n-1) + g(n-3)
h(n) = h(n-1) + h(n-4)
还有一些这样的功能,由于问题的规模,我不得不添加记忆,这很简单,如下所示:
memF = (map f' [0 ..] !!)
where f' x | x <=1 = 1
f' 2 = 2
f' x = memF(x-1) + memF(x-2)
memG = (map f' [0 ..] !!)
where f' x | x <=2 = 1
f' 3 = 2
f' x = memG(x-1) + memG(x-3)
这很好,所以我可以得到 (memF 100) + (memG 100) + ...
的答案并且我已经回答了问题,但是重复的代码很难看,我宁愿定义一个函数来生成记忆函数, 所以像:
mem d = (map f' [0 ..] !!)
where f' x | x < d = 1
f' x | x == d = 2
f' x = (mem d) (x-1) + (mem d)(x-d)
然后回答 mem 2 100 + mem 3 100 + ...
这失败了,或者至少缓存不起作用,我猜是因为每次调用都会重新创建数组,我想我可以使用 StateMonad 或记忆库,但我很想知道是否有办法在没有 Monads 的情况下做到这一点。请问有吗?
您需要另一个绑定以避免对 mem d
:
的递归调用
mem d = g
where g = (map f' [0 ..] !!)
f' x | x < d = 1
f' x | x == d = 2
f' x = g (x-1) + g (x-d)
调用 mem
时也要小心,因为每次调用 mem
都会创建自己的缓存。例如
mem 10 x + mem 10 y
不会缓存任何东西,而
let g = mem 10 in g x + g y
将使用相同的缓存。
另一种方法是对所有调用 mem d x
使用单个 "global" 缓存,对 (d,x)
对使用记忆。不过,这看起来有点棘手。
我已经解决了 Haskell 中的动态规划问题(实际上是欧拉计划问题),归结为斐波那契数列的推广:
f(n) = f(n-1) + f(n-2)
g(n) = g(n-1) + g(n-3)
h(n) = h(n-1) + h(n-4)
还有一些这样的功能,由于问题的规模,我不得不添加记忆,这很简单,如下所示:
memF = (map f' [0 ..] !!)
where f' x | x <=1 = 1
f' 2 = 2
f' x = memF(x-1) + memF(x-2)
memG = (map f' [0 ..] !!)
where f' x | x <=2 = 1
f' 3 = 2
f' x = memG(x-1) + memG(x-3)
这很好,所以我可以得到 (memF 100) + (memG 100) + ...
的答案并且我已经回答了问题,但是重复的代码很难看,我宁愿定义一个函数来生成记忆函数, 所以像:
mem d = (map f' [0 ..] !!)
where f' x | x < d = 1
f' x | x == d = 2
f' x = (mem d) (x-1) + (mem d)(x-d)
然后回答 mem 2 100 + mem 3 100 + ...
这失败了,或者至少缓存不起作用,我猜是因为每次调用都会重新创建数组,我想我可以使用 StateMonad 或记忆库,但我很想知道是否有办法在没有 Monads 的情况下做到这一点。请问有吗?
您需要另一个绑定以避免对 mem d
:
mem d = g
where g = (map f' [0 ..] !!)
f' x | x < d = 1
f' x | x == d = 2
f' x = g (x-1) + g (x-d)
调用 mem
时也要小心,因为每次调用 mem
都会创建自己的缓存。例如
mem 10 x + mem 10 y
不会缓存任何东西,而
let g = mem 10 in g x + g y
将使用相同的缓存。
另一种方法是对所有调用 mem d x
使用单个 "global" 缓存,对 (d,x)
对使用记忆。不过,这看起来有点棘手。