4

したがって、次のような 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"

これを行うと、2 番目のデータをロードするのに約 8 秒かかり、残りの機能を実行するのに約 3 秒かかります。

ただし、ショーの長さのデータを削除すると、点滅します

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

次に、すべての実際の機能が実行されるまで、少し一時停止します。

そこに seq を入れることで、遅延評価を防いだことが私の理解でした。私はそれらを間違って使用していますか?

4

2 に答える 2

11

はい。考慮すべき重要な点が 2 つありますseq。WHNF (weak-head normal form) に評価されsecondData、リストです。WHNF は、データが最も外側のコンストラクターに対して評価されることを意味し、最も外側のコンストラクターはsecondDataです:(空でない限り、コンストラクターは です[])。そう

secondData `seq` generateBars (barSize featureSet) secondData

secondDataが空のリストかどうか、または少なくとも 1 つの要素があるかどうかを判断するのに十分な作業のみを行います。

lengthリストのスパインを評価します。これは基本的に、構造全体を走査することによって、リスト内にいくつの要素があるかを判断することを意味します。これは、複数の要素を持つリストよりlengthも多くの作業を行うことを意味します。seq

deepseq( deepseqから) を使用してリストを完全に評価できますが、そうしたくない場合があります。 lengthリストをdeepseq完全にトラバースする必要があります。事前にその情報を知る必要がない場合、消費者もリストを再度スキャンする必要があるため、これは無駄な作業です。コンシューマーによっては、deepseq が最初にすべてのデータ構造を強制するため、これによりヒープ常駐も増加する可能性がありますが、アルゴリズムが完了するまでそれらは GC されません。

于 2012-07-04T01:16:07.670 に答える
3

seq値を弱頭正規形に強制するだけです。[]リストの場合、これは、リストがまたはに一致するかどうかを判断するのに十分なだけ評価されることを意味します_:_。純粋に名前に基づいて推測すると (タイプを指定していないため)、これまたはそのようなことが起こっているのです。「うん、ここにはデータがまったくない」と気付くのに十分なだけ評価されています。 .

通常のトリックはseq、リストの長さを呼び出すか、 を使用することdeepseqです。

于 2012-07-04T01:16:22.920 に答える