我有一个计算量很大的向量,我想在一个函数中建立索引,但是由于这个表从来没有在其他地方使用过,我不想传递这个向量,而是像记忆函数一样访问预先计算的值。
其想法是:
cachedFunction :: Int -> Int
cachedFunction ix = table ! ix
where table = <vector creation>
我注意到的一个方面是,我所看到的所有记忆示例都涉及递归,即使使用表来记忆,表中的值也依赖于表中的其他值。这与我的情况不同,在我的情况下,计算值是使用试错法找到的,但每个元素都是独立于另一个的。
如何在函数中实现缓存表?
2条答案
按热度按时间elcex8rz1#
你几乎是对的。问题是,你的例子基本上是这样的:
也就是说,
table
不会在不同的ix
之间共享。这与它碰巧不 * 依赖于 *ix
的事实无关(这在本例中很明显,但一般情况下并不如此)。因此,将它保存在内存中是没有用的,Haskell也不会这样做。但是,您可以通过将
ix
参数及其关联的where-block拉入结果中来改变这一点:也就是说
或更短,
在这种形式中,
cachedFunction
是constant applicative form,也就是说,尽管有一个函数类型,但它被编译器视为 * 一个常量值 *。它不是一个你可以计算为范式的值,但它将保持相同的表(它 * 不能 * 依赖于ix
;它的作用域中没有它)。erhoui1w2#
根据this answer,GHC永远不会重新计算在模块顶层声明的 values。(一次)第一次需要它,然后它就再也不会被请求了。(为简单起见,示例使用简单整数而不是向量)
输出:
我们可以看到,
table
在cachedFunction
被调用之前 * 没有 * 被计算,并且它只被计算一次,即使我们调用了cachedFunction
两次。