【问题标题】:Memoization in Haskell using premade data structures使用预制数据结构在 Haskell 中进行记忆
【发布时间】:2011-07-27 16:50:05
【问题描述】:

我发现 this answerthis wiki page 是 Haskell 中记忆化的绝佳介绍。然而,他们仍然给我留下了一个我希望得到回答的问题:

在我看来,使用的技术要求您“打开”(如“访问内部”)用于存储记忆的数据结构。例如,1 实现了一个表结构,2 实现了section 3 中的一个树。是否可以使用预制的数据结构做类似的事情?例如,假设您认为Data.Map 真的很棒,并且希望将您的记忆值存储在这样的Map 中。一种方法可以使用像这样的预制数据结构进行记忆,其中 实现结构本身,而是使用预制的结构?

希望有人能给我一个关于如何思考的提示,或者更有可能纠正我对功能性记忆的一般误解。

编辑:可以想到一种方法,但一点也不优雅:如果f :: a -> b,那么人们可能很容易制作一个记忆版本f' :: Map a b -> a -> (Map a b, b),其中第一个参数是记忆存储,输出对包含可能更新的存储和计算值。这种状态传递当然不是我想要的(虽然我猜它可以被包裹在一个 monad 中,但它比 12 中的方法丑几个数量级)。

编辑 2: 尝试表达我目前的(不正确的)想法可能会有所帮助。目前,我似乎一再违背自己的意愿将自己拉入无法解决的境地

import qualified Data.Map as Map
memo :: (Ord a) => [a] -> (a -> b) -> (a -> b)
memo domain f = (Map.!) storage
    where
      storage = Map.fromList (zip domain (map f domain))

我越看这个,我就越意识到我误解了一些基本的东西。你看,我觉得我的memo [True, False] 相当于1bool memoizer。

【问题讨论】:

  • 呃。阅读丹的回答,我确信“编辑 2”中的代码实际上没有任何问题。事实证明我只是错误地分析。它工作正常:-)

标签: haskell memoization


【解决方案1】:

如果您注意到,Data.Memocombinators 实际上依赖于“预制”Data.IntTrie。我相信您可以采用相同的代码并将 IntTrie 的使用替换为另一种数据结构,尽管它可能效率不高。

memoization 的一般思想是保存计算结果。在 Haskell 中,最简单的方法是将您的函数映射到一个表中,该表的每个参数都有一个维度。由于 Haskell 是惰性的(好吧,Haskell 中的大多数数据结构都是),它只会在您特别要求时评估给定单元格的值。 “表”基本上意味着“地图”,因为它会将您从键带到值。


[edit] 关于示例 2 的其他想法

如果我没记错的话,那么(Map.!) storage 第一次被强制计算给定键时,storage 结构将被完全拧干(尽管计算 f 不会发生,但给定的密​​钥)。所以第一次查找会导致额外的 O(n) 操作,n 是length domain。后续查找不会产生此成本。

像典型的 int 索引列表或 IntTrie 这样的惰性结构同样需要在调用查找时显示其结构,但与 Map 不同的是,它们不需要一次全部完成。在访问索引键之前,列表会被拧干。 IntTries 只拧出作为所需键的“前缀”(或后缀?不确定。可以通过任何一种方式实现)的整数键。索引 11, (1011) 将得出 1 (1)、2 (10)、5 (101) 和 11 (1011)。 Data.Memocombinators 只是将所有键转换为 Ints(或“位”),以便可以使用 IntTrie

附言有没有比“拧出”更好的短语?我想到了“力”、“脊椎”和“清单”这些词,但我想不出合适的词/短语。

【讨论】:

  • 重要的是要认识到IntTrieMap 的区别在于它的惰性——它能够为无限多个键存储值。您必须将映射“一次一个”添加到Map,因此它只能有有限多个映射,因此您不能使用它来存储无限参数空间的值(最有趣的参数空间是) .
  • (re: 懒惰地为无限键存储值)在这方面,IntTrie 与简单的List 相当。但是要到达条目 1000,您必须遍历(尽管不一定计算结果)列表中它前面的 999 个条目。使用 IntTrie,您只需遍历 log(1000) = ~10 个条目。
  • “在 Haskell 中,最简单的方法是……”使用 monad-memo 包,我发现它比我预期的更酷/更容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
  • 2018-02-28
  • 1970-01-01
  • 2020-10-25
  • 2011-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多