【问题标题】:Does this Haskell function memoize?这个 Haskell 函数可以记忆吗?
【发布时间】:2016-07-03 05:41:22
【问题描述】:

我想预先计算一些值,然后在需要进行进一步查找时使用这些值。我想出了以下几点:

import qualified Data.Vector.Unboxed as V

lcgen s =
  lc
  where
    lc 0 b  = lengths V.! b
    lc a b  = lengths V.! b - lengths V.! (a - 1) - 1
    lengths = V.fromList $ scanl1 ((+) . (1 +)) $ map length $ words s

该函数本质上返回两个单词之间使用的字符数。我使用它如下:

let lc = lcgen "some sentence with a lot of words"
lc 0 0 -- == 4
lc 0 1 -- == 13

在这个实现中,lengths 向量会被记忆吗?此外,我如何知道和/或确认这一点?

【问题讨论】:

  • 您可以将trace 添加到length (length = trace "building..." $ V.fromList ...) 并亲自查看
  • @Carsten 或者,您可以传递-ddump-simpl 选项并查看编译器生成的核心,然后检查那里。
  • @Bakuriu 这可能是 更好 选项是的 - 但你必须了解核心;)
  • @Carsten 谢谢。这就是我需要的。如果您可以发布作为答案,我会接受。

标签: haskell memoization


【解决方案1】:

如果您像这样将trace 添加到您的lengths

lengths = trace "building list..." $ V.fromList ...

每次计算lengths 值时,您都会看到输出

因为它应该只评估/构建每个lc = lcgen s一次

【讨论】:

    【解决方案2】:

    在这种情况下,lengths 显然无法记忆,因为它取决于外部函数的参数,这就是每次调用该函数时都会重新生成它的原因。

    如果没有这种依赖关系,它可能会被记忆。要检查是否发生这种情况,您可以使用 cmets 中建议的方法之一。为确保记忆确实发生,您可以使用标准方法,使用NOINLINE pragma 将所需片段提取到顶层。例如,

    {-# NOINLINE lengths #-}
    lengths :: Vector Int
    lengths =
      error "define me"
    

    【讨论】:

    • 我相信他的意思是“关于lc 函数的记忆”
    • @Bergi 是的,我做到了。谢谢你为我澄清。我将把这个答案理解为意味着 lc 函数将被记住。
    猜你喜欢
    • 1970-01-01
    • 2021-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-11
    • 2013-08-20
    • 2011-07-29
    相关资源
    最近更新 更多