seq不强迫评估

时间:2012-07-04 00:58:18

标签: haskell

所以我的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"

然后暂停一下,直到它贯穿所有实际功能。

这是我的理解,因为我在那里阻止了懒惰的评估。我用错了吗?

2 个答案:

答案 0 :(得分:11)

是。需要考虑两个要点:seq评估为WHNF(弱头普通形式),secondData是列表。 WHNF意味着数据将被评估到最外层的构造函数,secondData的最外层构造函数是:(除非它是空的,然后构造函数是[])。所以

secondData `seq` generateBars (barSize featureSet) secondData

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

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

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

答案 1 :(得分:3)

seq只会强迫弱头正常形态;对于列表,这意味着它的评估范围足以判断列表是否与[]_:_匹配。在猜测中,纯粹基于名称(因为你没有给出任何类型),这或类似的东西正在发生在你身上:它只是评估得足以实现“是的,这里的数据根本就没有了”

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