【问题标题】:Memoizing cheap side-results记住廉价的副作用
【发布时间】:2012-02-26 05:41:59
【问题描述】:

我想记住一个带有类型的函数,比如说,

f :: Int -> Integer

我可以很容易地做到这一点,例如使用MemoCombinators 包,例如:

f_ = Memo.integral f

但是,当给定一对(x, f x) 时,在给定f x 的情况下,还有很多其他点可以很容易地计算f

freebies :: (Int, Integer) -> [(Int, Integer)]

但是给定一个点x',计算一些xelem x' . map fst $ freebies (x, f x) 并不便宜。所以我想在这些额外的(x', y') 对可用时存储它们,以便以后可以有效地计算f x'

我的问题是,有什么好的方法来记忆这样的功能?

【问题讨论】:

  • 我们在谈论什么样的函数f?它似乎基本上是递归的,还是计算增量近似?除非知道xx' 之间的关系,否则这个问题没有通用的解决方案。
  • 您的问题是关于如何通过记忆所有计算出的 f(x) 来计算 f⁻¹(y) 吗?
  • dfelmstr:我的出发点是我同时拥有ffreebies,但f 不是递归的,因此计算f x' 并不涉及计算f x,即使@ 987654341@ 在map fst $ freebies (x, f x)
  • nist: 不,我想计算所有的f x1, f x2, ..., f xn,但如果f xj 不那么贵就好了如果它已经是来自f xi 的一些i<j 的免费赠品,则再次计算部分。

标签: haskell memoization


【解决方案1】:

要使用 pure 记忆来做到这一点,您需要找到一种方法将您的免费赠品的xs 映射回生成它的点。如果您想考虑纯记忆的功能,请不要将其视为更新的缓存表;相反,将其视为逐渐简化的数据依赖图。您需要一种方法让免费赠品指向计算它们的内容。

假设你有这个:

-- Representative k finds a k', where it is easy to calculate
-- k from (k')'s value (this calculation is the Value -> Value
-- function)
-- There should be multiple (k')'s per k; and representative k' 
-- on one of those should return (k', const v), where v is the
-- value.
representative :: Key -> (Key, Value -> Value)

然后你就可以记忆了:

table = memoKey go
    where
    go k = let (k', vf) = representative k in
           vf (table k')

其中memoKeyKey 的备忘录。

请记住,Value 可能是一个更复杂的类型,它包含计算免费赠品所需的信息,然后您可以为最终用户丢弃额外的信息。

如果您不能将freebies 反转为representative 的形式,那么我认为您对 记忆策略不走运。这是因为如果您按照建议的方式进行操作,则免费赠品表中的值将取决于评估的内容首先,这在纯 Haskell 中是一个禁忌。 (即使你知道这些值是相同的,纯粹的记忆策略甚至不能依赖于评估顺序)

您也可以使用具有显式状态保存表的方法,或基于unsafePerformIO 的不纯备忘录表。

【讨论】:

    猜你喜欢
    • 2011-01-24
    • 2013-01-04
    • 2020-10-06
    • 2016-02-07
    • 1970-01-01
    • 1970-01-01
    • 2018-07-19
    • 2011-10-30
    • 2010-10-24
    相关资源
    最近更新 更多