这个 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
一次
我想预先计算一些值,然后在我需要进行进一步查找时使用这些值。我想出了以下内容:
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