【问题标题】:seq not forcing evaluationseq 不强制评估
【发布时间】:2012-07-04 00:58:18
【问题描述】:

所以我的 haskell 程序看起来像这样:

main = do
    secondData <- loadSecondBars "output.data"
    putStrLn $ "Generated Second Data " ++ (show $ length secondData)
    let tenMinBars = secondData `seq` generateBars (barSize featureSet) secondData
    putStrLn $ "Generated Ten Minute Bars " ++ (show $ length tenMinBars)
    let combinedData = seq tenMinBars sortBars (tenMinBars ++ secondData)
    putStrLn $ "Generated Combined" ++ (show $ length combinedData)
    let completedOrderManager = evalState (runBar combinedData) startState
    putStrLn "Ran Algo"

这样做需要大约 8 秒来加载我的第二个数据,然后大约 3 秒来完成其余的功能。

但是,如果我删除显示长度数据,它会闪烁

"Generated Second Data"
"Generated Ten Minute Bars"
"Generated Combined"
"Ran Algo"

然后暂停一下,直到它运行完所有实际功能。

我的理解是,在其中包含 seq 可以防止惰性评估。我用错了吗?

【问题讨论】:

  • 是的,seq 将在返回第二个参数之前评估第一个参数。如我所见,这里的问题是 let tenMinBars = ... 等不会评估 seq 自身,因此 seq 的第一个参数仅在评估 let 表达式时才被评估。不过,据我所知!我还是个 Haskell 新手!
  • @cool_me5000 - 这可能是问题的一部分,但我认为这里没有足够的代码可以确定。这取决于runBar 以及completeOrderManager 会发生什么。

标签: haskell


【解决方案1】:

是的。有两点需要考虑:seq 评估为 WHNF(弱头范式),secondData 是一个列表。 WHNF表示数据会被求值到最外层的构造函数,secondData的最外层构造函数是:(除非是空的,那么构造函数就是[])。所以

secondData `seq` generateBars (barSize featureSet) secondData

只会做足够的工作来确定secondData 是否为空列表,或者它是否具有至少一个元素。

length 评估列表的脊椎,这基本上意味着它通过遍历完整结构来确定列表中有多少元素。这意味着对于超过 1 个元素的列表,length 将比 seq 做更多的工作。

您可以使用deepseq(来自deepseq)来全面评估列表,但您可能不想这样做。 lengthdeepseq 必须完全遍历列表。如果您不需要提前知道该信息,那么这是浪费精力,因为您的消费者还必须再次遍历该列表。根据消费者的不同,这也可能会增加堆驻留,因为 deepseq 将首先强制所有数据结构,但直到算法完成后才会对它们进行 GC。

【讨论】:

    【解决方案2】:

    seq 仅将值强制为弱头范式;对于列表,这意味着它仅评估足以判断列表是否匹配[]_:_。猜测一下,纯粹基于名称(因为您没有给出任何类型),这或类似的事情就是发生在您身上的事情:它只是评估到足以意识到“是的,这里根本没有数据” .

    通常的技巧是在列表长度上调用seq 或使用deepseq

    【讨论】:

      猜你喜欢
      • 2016-06-28
      • 2015-08-02
      • 2017-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-29
      • 2012-02-01
      • 1970-01-01
      相关资源
      最近更新 更多