What is the lifetime of a memoized value in a functional language like Haskell?
在具有惰性语义的纯函数语言(如haskell)中,计算结果被记忆化,这样具有相同输入的函数的进一步评估就不会重新计算该值,而是直接从记忆化值的缓存中获取该值。
我想知道这些记忆值是否在某个时间点被回收?
想象一个程序执行密集的数值分析:例如,使用二分法算法查找数十万个数学函数的根。
每次程序用一个特定的实数计算一个数学函数时,结果都会被记忆。但可能性很小在算法过程中会再次出现完全相同的实数,从而导致内存泄漏(或者至少是非常糟糕的使用)。
我的想法是,记忆化的值可能只是简单地"限定"到程序中的某个内容(例如当前的延续、调用堆栈等),但我在这个主题上找不到实用的内容。
我承认我没有深入研究haskell编译器实现(lazy?)但是,有人能给我解释一下它在实践中是如何工作的吗?
编辑:好吧,我从最初的几个答案中理解了我的错误:纯粹的语义意味着引用的透明性,这反过来并不意味着自动记忆,但只是保证它不会有问题。
我认为网络上的一些文章误导了这一点,因为从初学者的角度来看,参考透明性似乎很酷,因为它允许隐式记忆。
Haskell不会自动记忆函数调用,因为这会很快消耗大量的内存。如果你自己做记忆,你可以选择记忆的功能范围。例如,假设您有这样定义的斐波那契函数:
这里的memoization只在对
号
然后保存memoized列表,直到垃圾收集器确定没有更多方法从程序的任何部分到达
My idea is that maybe memoized values are simply"scoped" to something in the program (for example to the current continuation, call stack, etc.), but I was unable to find something practical on the subject.
号
这是正确的。具体来说,当你看到如下情况时:
1 2 3 4 5 | fun x y = let a = ..... b = .... c = .... in .... |
或等效的WHERE子句,在实际使用之前,不可计算值a、b和c(或可立即计算,因为严格度分析仪可以保证稍后对值进行评估)。但是,当这些值依赖于当前函数参数(这里是x和y)时,运行时很可能不会记住x和y的每一个组合以及结果a、b和c。
还要注意,在纯语言中,完全不记住值也是可以的——这只是在内存比CPU时间便宜的情况下才是可行的。
所以,你的问题的答案是:没有这样的事情,中间人的一生会导致哈斯克尔。所有人都可以说,当需要时,评估值将在那里。