Haskell 中的部分记忆
我试图找到一种好方法,使用 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)
方法1是我想要的方法,但是它似乎不起作用。我认为这是因为每次调用 partFib
时都会“重新创建”fib
函数,从而丢弃了记忆。 fib
不依赖于 partFib
的输入,因此您会假设编译器可以提升它,但显然 GHC 不能那样工作。
方法2是我最终的做法。哎呀,很多丑陋的接线。
有谁知道更好的方法来做到这一点?
I'm trying to find a good way to memoize a function for only part of its domain (non-negative integers) in Haskell, using Data.MemoCombinators
.
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)
Approach 1 is how I would like to do it, however, it doesn't seem to work. I assume this is because the fib
function is "recreated" every time partFib
is called, throwing away the memoization. fib
doesn't depend on the input of partFib
, so you would assume that the compiler could hoist it, but apparently GHC doesn't work that way.
Approach 2 is how I end up doing it. Eerk, a lot of ugly wiring.
Does anybody know of a better way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不太确定什么对你来说“丑陋”,但是通过将记忆操作从
n
的函数中提升出来,你可以在仅使用单个顶级标识符的情况下进行适当的记忆。Not quite sure what's "ugly" to your eye, but you can have proper memoization while using only a single top-level identifier by lifting the memoization operation out of the function of
n
.嗯,稍微分开一下怎么样:
现在您需要使用 doFib。
Hmm what about separating things a bit:
Now you need to use doFib.
库中有一个用于此目的的组合器:
回想一下,
id
从技术上讲是一个记忆器(它不会记忆:-),所以你可以这样做:There is a combinator in the library for this purpose:
Recall that
id
is technically a memoizer (which does not memoize :-), so you can do: