Haskell 哈斯克尔的部分回忆录
我正试图找到一种好方法,使用Haskell 哈斯克尔的部分回忆录,haskell,ghc,memoization,Haskell,Ghc,Memoization,我正试图找到一种好方法,使用Data.MemoCombinators,在Haskell中只记忆函数的一部分域(非负整数) import Data.MemoCombinators --approach 1 partFib n | n < 0 = undefined | otherwise = integral fib n where fib 0 = 1 fib 1 = 1 fib k = partFib (k-1) + partFib (k-2) --a
Data.MemoCombinators
,在Haskell中只记忆函数的一部分域(非负整数)
import Data.MemoCombinators
--approach 1
partFib n | n < 0 = undefined
| otherwise = integral fib n where
fib 0 = 1
fib 1 = 1
fib k = partFib (k-1) + partFib (k-2)
--approach 2
partFib2 n | n < 0 = undefined
| otherwise = fib n
fib = integral fib'
where
fib' 0 = 1
fib' 1 = 1
fib' n = partFib2 (n-1) + partFib2 (n-2)
import Data.memos
--方法1
partFib n | n<0=未定义
|否则=积分fib n,其中
fib 0=1
fib 1=1
fibk=partFib(k-1)+partFib(k-2)
--方法2
partFib2 n | n<0=未定义
|否则=fib n
fib=积分fib'
哪里
fib'0=1
fib'1=1
fib'n=partFib2(n-1)+partFib2(n-2)
方法1是我想怎么做的,但是,它似乎不起作用。我认为这是因为每次调用partFib
时,fib
函数都被“重新创建”,从而丢弃了记忆fib
不依赖于partFib
的输入,因此您可以假设编译器可以提升它,但显然GHC不是这样工作的
方法2是我最终如何做到这一点。Eerk,很多丑陋的线路
有人知道更好的方法吗?不太清楚什么是你眼中的“丑陋”,但你可以通过将记忆操作从n
的功能中取消,在只使用一个顶级标识符的情况下进行正确的记忆
partFib3 = \n -> if n < 0 then undefined else fib' n
where fib 0 = 1
fib 1 = 1
fib k = partFib3 (k-1) + partFib3 (k-2)
fib' = integral fib
partFib3=\n->如果n<0,则未定义else fib'n
其中fib 0=1
fib 1=1
fibk=partFib3(k-1)+partFib3(k-2)
fib'=积分fib
嗯,把东西分开一点怎么样:
fib 0 = 0
fib 1 = 1
fib x = doFib (x-1) + doFib (x-2)
memFib = Memo.integral fib
doFib n | n < 0 = fib n
| otherwise memFib n
fib 0=0
fib 1=1
fibx=doFib(x-1)+doFib(x-2)
memFib=Memo.integral fib
doFib n | n<0=fib n
|否则memFib n
现在您需要使用doFib。库中有一个用于此目的的组合器:
开关p a b
在p
为真时使用备忘表a
,在p
为假时使用备忘表b
回想一下,id
在技术上是一个回忆录器(它不回忆录:-),因此您可以执行以下操作:
partFib = Memo.switch (< 0) id Memo.integral fib'
where
...
partFib=Memo.switch(<0)id Memo.integral fib'
哪里
...
谢谢,这比我的好。没有什么是真正的“丑陋”,我只是想让定义看起来尽可能类似于天真的斐波那契实现。为什么这会有不同?在语义上是否与f=\n->e
完全相同?@Dan,在语义上,是的。但备忘录正在进入操作领域。前者中的n
的作用域是where
子句,而后者中的n
的作用域不是,因此改变了where子句中thunk的共享方式。@Dan,最近这篇关于共享变量绑定的文章有更详细的内容:Richard Bird与Haskell的功能性思考的第7章也是关于这个主题的一篇很好的阅读。谢谢。我也喜欢这个。它将函数定义与记忆内容的定义清晰地分开。所谓“记忆器(不记忆:-)”,您的意思是它的类型是Memo a
,因此类型系统允许您将其用作记忆器?
partFib = Memo.switch (< 0) id Memo.integral fib'
where
...