使记忆成为Haskell默认行为的选项
我已经看到了Haskell中所有其他的记忆技巧和技巧,但是我正在寻找的是编译器/解释器级别的简单实现,它为我处理记忆。
例如,考虑斐波那契函数的以下代码:
fib 0 = 1
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
我想为ghc(或任何其他Haskell编译器)提供某种编译器选项,默认情况下使用memoization来执行上面的代码。 例如,要计算“fib 10”,首先需要计算“fib 8”和“fib 9”。 而且,计算“fib 9”取决于第一次计算“fib 8”。 所以,当计算“fib 10”时,我希望编译器/解释器理解并计算“fib 8”只有一次。
请注意,我不想编写一个新的处理记忆的斐波那契函数(就像在Haskell中所有其他记忆问题一样)。 我想要的是保持上面的功能,并仍然有备忘录。 我不知道Haskell编译器是否有这种能力,这是我的问题的一部分。 你知道一个Haskell编译器可以给我这个吗?
谢谢
编译器通常不会提供“memoize”选项,因为很难知道程序员在何处以及如何执行memoization。 记忆本质上是交易时间和空间的要求。
现在,如果您愿意以稍微不同的方式编写函数,那么可以将函数的定义和使用的记忆技术分开。
import Data.RunMemo (Memoizable, runMemo, noMemo)
import Data.MemoCombinators as Memo (integral)
fibMemoizable :: Memoizable (Integer -> Integer)
fibMemoizable recurse = go where
go 0 = 1
go 1 = 1
go n = recurse (n - 1) + recurse (n - 2)
fastFib :: Integer -> Integer
fastFib = runMemo Memo.integral fibMemoizable
slowFib :: Integer -> Integer
slowFib = runMemo noMemo fibMemoizable
这使用Luke Palmer的数据memocombinators包,以及我自己的玩具包runmemo。 请注意,它的内容与您所写的内容相同,只不过它会调用recurse
调用的recurse
。 虽然这可以被编译进一个编译器,但是我没有看到任何理由,因为Haskell足以表达出足够的表达能力来解决这个问题,而不需要编译器知道我们正在做什么。
上一篇: An option to make memoization the default behaviour of Haskell
下一篇: Why does GHC consider the LHS *syntactically* when inlining?