在某处有基于对象身份的,线程安全的memoization库吗?

时间:2011-07-29 19:40:31

标签: haskell memoization

3 个答案:

答案 0 :(得分:6)

如果想要基于对象标识进行记忆,而不是相等,则可以使用该语言中内置的现有惰性机制。

例如,如果您有这样的数据结构

data Foo = Foo { ... }
expensive :: Foo -> Bar

然后你可以添加要被记忆的值作为额外的字段,并让懒惰为你处理剩下的事情。

data Foo = Foo { ..., memo :: Bar }

为了更容易使用,添加一个智能构造函数来打结。

makeFoo ... = let foo = Foo { ..., memo = expensive foo } in foo

虽然这比使用库稍微不那么优雅,并且需要修改数据类型才真正有用,但这是一种非常简单的技术,所有线程安全问题都已经为您解决了。

答案 1 :(得分:3)

stable-memo似乎正是您所需要的(虽然我不确定它是否可以处理多个线程):

  

尽管大多数备忘录组合器基于相等性进行memoize,但是stable-memo基于之前是否已经将完全相同的参数传递给函数(即,在内存中是相同的参数)来进行。

     
      
  • stable-memo仅评估WHNF的密钥。

  •   
  • 这可能更适合于具有周期的图形上的递归函数。

  •   
  • stable-memo不会保留到目前为止看到的密钥,如果不再使用它们,它们就会被垃圾收集。如果发生这种情况,将使用终结器来从备忘录表中删除相应的条目。

  •   
  • Data.StableMemo.Weak提供了另一组组合器,它们也避免保留函数的结果,只有在尚未进行垃圾回收时才重用结果。

  •   
  • 函数的参数没有类型类约束。

  •   
     

stable-memo对于碰巧具有相同值但不是相同堆对象的参数不起作用。这排除了许多备忘录的候选者,例如最常见的例子,天真的Fibonacci实现,其域是机器Ints;但它仍然可以用于某些领域,例如懒惰的自然。

答案 2 :(得分:1)

Ekmett刚刚上传了一个处理这个问题的图书馆(在HacPhi制作):http://hackage.haskell.org/package/intern。他向我保证它是线程安全的。

编辑:实际上,严格来说,我意识到这有点不同。但我认为你可以将它用于你的目的。它实际上更像是一个stringtable-atom类型的实习库,适用于任意数据结构(包括递归数据结构)。它在内部使用WeakPtrs来维护表。但是,它使用Int来索引值以避免结构相等性检查,这意味着将它们打包到数据类型中,当您想要显然实际上StableName时。所以我意识到这回答了一个相关的问题,但需要修改你想要避免的数据类型......