所以我的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"
然后暂停一下,直到它贯穿所有实际功能。
这是我的理解,因为我在那里阻止了懒惰的评估。我用错了吗?
答案 0 :(得分:11)
是。需要考虑两个要点:seq
评估为WHNF(弱头普通形式),secondData
是列表。 WHNF意味着数据将被评估到最外层的构造函数,secondData
的最外层构造函数是:
(除非它是空的,然后构造函数是[]
)。所以
secondData `seq` generateBars (barSize featureSet) secondData
只会做足够的工作来确定secondData
是否为空列表,或者是否至少有一个元素。
length
评估列表的主干,这基本上意味着它通过遍历整个结构来确定列表中有多少元素。这意味着,对于包含1个以上元素的列表,length
将比seq
做更多的工作。
您可以使用deepseq
(来自deepseq)来完整评估列表,但您可能不想这样做。 length
和deepseq
必须完全遍历该列表。如果您不需要提前知道这些信息,这是浪费精力,因为您的消费者也必须再次遍历列表。根据使用者的不同,这也可能会增加堆驻留时间,因为deepseq会先强制所有数据结构,但是在算法完成之后它们才会被GC进行。
答案 1 :(得分:3)
seq
只会强迫弱头正常形态;对于列表,这意味着它的评估范围足以判断列表是否与[]
或_:_
匹配。在猜测中,纯粹基于名称(因为你没有给出任何类型),这或类似的东西正在发生在你身上:它只是评估得足以实现“是的,这里的数据根本就没有了”
通常的诀窍是在列表的长度上调用seq
或使用deepseq
。