7

したがって、Haskellseq関数は最初の引数の評価を強制し、2 番目の引数を返します。したがって、これは中置演算子です。式の評価を強制したい場合、直観的にそのような機能は単項演算子になります。だから、代わりに

seq :: a -> b -> b

それはそのようになります

seq :: a -> a

したがって、必要な値が の場合a、なぜ戻りb、どのように の戻り値を構築しますかb。明らかに、私は Haskell を考えていません。:)

4

1 に答える 1

18

考え方としてa `seq` bは、「評価する」ということではなく、 との間に依存関係をa作り、評価するときに自分も評価するということです。abba

これは、たとえば、これは完全に冗長であることを意味します: を評価するときにa `seq` aHaskell に評価するように指示しているのです。同じ論理で、引数が 1 つだけでも、単にそれ自体を記述することと何ら変わりはありません。aaseq aa

seq aどういうわけか評価するだけでaはうまくいきません。問題は、seq aそれ自体が評価されない可能性がある式であることです。たとえば、ネストされたサンクの奥深くにある可能性があります。そのため、式全体を評価するようになった場合にのみ関連性が高まります。seq aその時点では、aとにかくそれ自体を評価していたはずです。

@Rhymoid の厳密な折り畳み ( foldl') での使用例は良い例です。acc私たちの目標は、最終結果を評価するとすぐに中間累積値 ( ) が各ステップで完全に評価されるようにフォールドを作成することです。これはseq、累積値と再帰呼び出しの間にa を追加することによって行われます。

foldl' f z (x:xs) = 
  let z' = f z x in z' `seq` foldl' f z' xs

これを、フォールド内のseq各アプリケーション間の長いチェーンとして視覚化し、それらすべてを最終結果に接続することができます。fこのようにして、最終的な式 (つまり、リストを合計して得られる数値) を評価すると、中間値 (つまり、リストをたどったときの部分合計) が厳密に評価されます。

于 2016-09-22T17:23:58.930 に答える