这个 Haskell 函数会记忆吗?

Does this Haskell function memoize?

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

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

函数本质上是 returns 两个单词之间使用的字符数。我是这样使用的:

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

在这个实现中,lengths 向量会被记忆吗?此外,我怎么知道 and/or 确认这一点?

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

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

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

如果您像这样向 lengths 添加 trace

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

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

因为它应该只 evaluated/build 每个 lc = lcgen s

一次