这个包有一些函数可以将递归函数转换为动态编程递归函数,以获得更好的性能:
不幸的是,他们只有一个最简单的函数类型的例子,并且没有关于如何使用2个变量的函数的例子。我在哪里可以找到如何将[Int] -> Int -> Int
函数转换为动态编程函数的示例?文档说memo2需要两个Memo
作为第一个参数,但我不确定这意味着什么。
解决方案:
正如Hammar所描述的那样,而不是将函数定义为:
foo :: [Int] -> Int -> Int
foo list value = ...
使用memo2:
import qualified Data.MemoCombinators as Memo
foo = Memo.memo2 (Memo.list Memo.integral) Memo.integral foo'
where ... (define foo' with recursive calls to foo.)
答案 0 :(得分:11)
库定义类型Memo a
,它是带有a
类型参数的函数的“memoizer”。理解如何使用此库的关键是了解如何使用和组合这些存储器。
在简单的情况下,您有一个参数函数和一个简单的memoizer,例如Fibonacci函数和Integral
参数的memoizer。在这种情况下,我们通过将memoizer应用于要记忆的函数来获取memoized函数:
fib = Memo.integral fib'
where
fib' 0 = 0
fib' 1 = 1
fib' x = fib (x-1) + fib (x-2)
一些记忆者会使用参数来定制他们的行为,例如arrayRange
。在以下示例中,fib n
仅在n
介于1和100之间时才会被记忆。
fib = Memo.arrayRange (1, 100) fib'
where ...
该库还提供组合器,用于构建更简单的memoizer。例如,list
会将a
的备忘录转换为[a]
的记事本。
最后,为了记住多个参数的函数,有函数memo2
和memo3
,它们为每个参数加上一个函数的memoizer并返回一个memoized函数。
因此,为了记住你的双参数函数,我们需要使用memo2
。我们可以将integral
memoizer用于Int
参数,对于[Int]
参数,我们可以使用list integral
。把这些放在一起,我们得到这样的结论:
memo2 (list integral) integral foo
但是,如果您知道数字在某个指定范围内,您还可以使用更具体的记忆。例如,如果列表中的数字介于1和10之间,而第二个参数介于15和20之间:
memo2 (list $ arrayRange (1, 10)) (arrayRange (15, 20)) foo
这是否有意义取决于您的申请。
答案 1 :(得分:2)
每种类型和文档,我相信
foo :: [Int] -> Int -> Int
应按照
记忆memo2 (list integral) integral foo
(免责声明:我没有使用过数据记忆合作者)。