Haskell 函数式编程语言中的自动记忆

Haskell 函数式编程语言中的自动记忆,haskell,functional-programming,memoization,Haskell,Functional Programming,Memoization,我一直认为Haskell会做一些自动智能记忆。例如,朴素的斐波那契实现 fib 0 = 0 fib 1 = 1 fib n = fib (n-2) + fib (n-1) 因为那样会很快。现在我读了,似乎我错了——哈斯克尔似乎不做自动回忆录。还是我理解错了什么 是否有其他语言可以自动(即隐式而非显式)记忆 实现备忘录化的常见方法有哪些?在我看到的所有示例实现中,它们都使用hashmap,但其大小没有任何限制。显然,这在实践中是行不通的,因为你需要某种限制。鉴于此,它变得更加复杂,因为当你达到极

我一直认为Haskell会做一些自动智能记忆。例如,朴素的斐波那契实现

fib 0 = 0
fib 1 = 1
fib n = fib (n-2) + fib (n-1)
因为那样会很快。现在我读了,似乎我错了——哈斯克尔似乎不做自动回忆录。还是我理解错了什么

是否有其他语言可以自动(即隐式而非显式)记忆

实现备忘录化的常见方法有哪些?在我看到的所有示例实现中,它们都使用hashmap,但其大小没有任何限制。显然,这在实践中是行不通的,因为你需要某种限制。鉴于此,它变得更加复杂,因为当你达到极限时,你必须扔掉一些数据。这就变得复杂了:极限应该是动态的吗?经常使用的函数应该比不经常使用的函数有更高的极限吗?当你达到极限时,你会扔掉什么?只是最近用过的?在这种情况下,还需要对数据进行排序。您可以使用链表和哈希映射的某种组合来实现这一点。这是常见的方式吗

您是否可以链接(或参考)一些常见的实际实现

谢谢, 阿尔伯特


编辑:我最感兴趣的是我描述的那个问题,即如何实现这样的限制。任何涉及这一点的论文的参考资料都会非常好


编辑:可以找到一些自己对示例实现(有限制)的想法


编辑:我不是在试图解决特定应用程序中的特定问题。我正在寻找记忆的通用解决方案,它可以全局应用于(纯函数)程序的所有函数(因此,不实现内存限制的算法不是解决方案)。当然(可能)没有最优/最佳解决方案。但这也让我的问题不那么有趣

为了尝试这种解决方案,我考虑将其作为优化添加到Haskell中。我真的很想知道那会有多好


我想知道是否有人已经这样做了。

不,Haskell不自动记忆函数。它所做的是存储值,所以如果

x = somethingVeryLong
和你在同一范围内的其他地方

y = f x
z = g x
那么x将只计算一次


显示如何使用各种键和查找表存储已记录的值。回忆录通常在一次调用较大的函数时使用,因此回忆录的值不会永远挂起(正如您所说,这将是一个问题)。如果你想要一本回忆录,它也会使用LRU或其他东西忘记旧的价值观,那么我认为你可能需要把它放在状态单子或其他东西中;你不能用传统的记忆方法让Haskell表现得像那样

没有确切的答案,但这一页:提供了有关Haskell中记忆的想法,还显示了可能感兴趣的基于列表的斐波那契序列实现。

我在评论中说,您的要求听起来像垃圾收集。我这样认为是因为您对管理有限的内存池感兴趣,时不时地清除它,这样它就不会消失

现在想想,它更像是一个虚拟内存。你可以在维基百科的页面上看到解决这类问题的各种方法,比如“最近没用过”、“老化”、“时钟”、“第二次机会”等等

然而,回忆录通常不是通过限制保留的结果来完成的;上述算法所需的变异通常不是haskellish。不过,不要因此而气馁。你有一些有趣的想法,这些想法对探索哈斯凯尔·图斯法的记忆可能性很有价值

有时,一个特定的记忆问题很适合有限的记忆。例如,两个基因序列的对齐可以通过动态规划(见维基百科)和二维记忆表来完成。但是,由于给定单元格的DP解决方案仅取决于前一行的结果,因此您可以从底部开始,丢弃与当前行的距离大于1的行。斐波那契数是一样的:为了计算下一个数,只需要序列中的前两个数。如果您感兴趣的只是第n个数字,那么您可以更早地放弃任何内容

大多数内存化都是为了加速存在共享子问题的递归算法。许多这样的问题并没有一种简单的方法来排序评估,从而丢弃不再需要的结果。在这一点上,您只是在猜测,使用启发式(如使用频率)来确定谁可以访问有限的资源

哈斯克尔似乎不做自动记忆。还是我理解错了什么

不,哈斯克尔没有。但是,共享表达式只计算一次。在Paul Johnson给出的示例中,
x
作为。
y
z
都可以引用
x
,因为
x
在范围内,并且它们引用相同的位置。一旦必须对
x
进行评估,将只对其进行一次评估,并且只保留评估结果。所以这并不是真正的回忆录,而是实施的结果

是否有其他语言可以自动(即隐式而非显式)记忆

我在一些python源代码中看到了decorator。当然,您可以完全为它创建自己的装饰器/实现。完成LRU和其他您想要使用的策略

实现备忘录化的常见方法有哪些

没有真正的
通用
方法来实现回忆录。对于类似fib的模式(只有一个参数,是一个数字),fib示例中使用的回忆录可以设计一个通用模式
: fib ( n -- n )
    dup 1 > [
        [ 1 - fib ]
        [ 2 - fib ]
        bi +
    ] when ;
MEMO: fib ( n -- n )
    dup 1 > [
        [ 1 - fib ]
        [ 2 - fib ]
        bi +
    ] when ;
F := proc(n) option remember;
    if n<2 then n else F(n-1)+F(n-2)
    end if
end proc;