Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Haskell这样的函数式语言中,记忆值的生命周期是多少?_Haskell_Functional Programming_Memoization - Fatal编程技术网

在Haskell这样的函数式语言中,记忆值的生命周期是多少?

在Haskell这样的函数式语言中,记忆值的生命周期是多少?,haskell,functional-programming,memoization,Haskell,Functional Programming,Memoization,在具有惰性语义的纯函数式语言(如Haskell)中,计算结果会被存储,因此对具有相同输入的函数的进一步求值不会重新计算值,而是直接从存储值的缓存中获取 我想知道这些记忆值是否会在某个时间点被回收 如果是这样,则意味着必须在以后重新计算已记忆的值,并且记忆的好处并不那么明显 如果没有,那么好吧,这是聪明的缓存一切。。。但这是否意味着一个程序——如果运行足够长的时间——将 总是消耗越来越多的内存 想象一个执行密集数值分析的程序:例如,使用二分法算法查找数十万个数学函数列表的根 每次程序用一个特定的实

在具有惰性语义的纯函数式语言(如Haskell)中,计算结果会被存储,因此对具有相同输入的函数的进一步求值不会重新计算值,而是直接从存储值的缓存中获取

我想知道这些记忆值是否会在某个时间点被回收

  • 如果是这样,则意味着必须在以后重新计算已记忆的值,并且记忆的好处并不那么明显
  • 如果没有,那么好吧,这是聪明的缓存一切。。。但这是否意味着一个程序——如果运行足够长的时间——将 总是消耗越来越多的内存
  • 想象一个执行密集数值分析的程序:例如,使用二分法算法查找数十万个数学函数列表的根

    每次程序用一个特定的实数计算一个数学函数时,结果都会被记录下来。但这种可能性很小 在算法执行期间,完全相同的实数将再次出现,导致内存泄漏(或者至少是非常糟糕的使用)

    我的想法是,可能记忆值只是“范围”到程序中的某个内容(例如当前的延续、调用堆栈等),但我无法找到关于这个主题的实用内容

    我承认我没有深入研究Haskell编译器的实现(lazy?),但是,有人能给我解释一下它在实践中是如何工作的吗


    编辑:好的,我从前面的几个答案中理解了我的错误:纯语义意味着引用透明性,而这反过来并不意味着自动记忆,只是保证不会有问题

    我认为网络上的一些文章对此有误导性,因为从初学者的角度来看,引用透明属性似乎很酷,因为它允许隐式记忆。

    Haskell不会自动记忆函数调用,正是因为这会快速消耗大量内存。如果你自己做记忆,你可以选择记忆函数的范围。例如,假设斐波那契函数的定义如下:

    fib n = fibs !! n
        where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
    
    在这里,只需一次调用
    fib
    ,就可以完成记忆,而如果您将
    fibs
    放在顶层

    fib n = fibs !! n
    
    fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
    
    然后,将保留已记忆的列表,直到垃圾收集器确定没有更多的方法可以从程序的任何部分访问
    fibs

    我的想法是,可能记忆值只是“范围”到程序中的某个内容(例如当前的延续、调用堆栈等),但我无法找到关于这个主题的实用内容

    这是正确的。具体来说,当您看到以下内容时:

    fun x y = let
        a = .....
        b = ....
        c = ....
    in ....
    
    或等效where条款,在实际使用之前,不得计算值a、b和c(或可立即计算值,因为严格度分析仪可以证明这些值将在以后进行评估)。但是当这些值依赖于当前函数参数(这里是x和y)时,运行时很可能不会记住x和y的每一个组合以及结果a、b和c

    还要注意的是,在纯语言中,完全不记住这些值也是可以的——这只适用于内存比CPU时间便宜的情况


    所以你的问题的答案是:Haskell中不存在中介结果的生存期。所有人都可以说,求值值会在需要时出现。

    +1对于这个具有启发性的示例,尽管我打赌在这种情况下,编译器实际上会看到fibs不需要是局部值,并将其无声地提升到顶部。@Ingo:我的印象是编译器不会在lambda之外浮动let,正是因为这可能会对内存使用产生重大影响,但我可能错了。请注意,即使是在内存化fib的情况下,当函数fib不再可访问时,fibs值也可能会被垃圾收集(ghc会这样做)。你们要找的词是,也请参见。这是Haskell标准强制要求的行为吗?或者,GHC就是这样做的吗?看到了吗