1

次の Haskell 型定義があります。

import Data.Sequence(Seq, length)
import Data.ByteString.UTF8(ByteString)

type StringSeq = Seq ByteString

StringSeqで厳密な評価を強制したい型の式がありdeepseqます。したがって、のインスタンスを定義する必要がありますNFData。私は次のことをしました:

import Control.DeepSeq(NFData, deepseq)

instance NFData ByteString

instance NFData a => NFData (Seq a) where
  rnf s = rnf (length s)

そこで、シーケンス自体の評価を強制するために、シーケンスの長さを計算します。これは機能しているように見えますが、これは正しい実装ですか? より良いものはありますか?シーケンスの長さを計算するとオーバーヘッドが大きくなりすぎませんか?

4

2 に答える 2

1

厳密性のためにモナドを定義できます

data Strict a = Strict {fromStrict :: !a}
instance Monad Strict where
   return = Strict
   (Strict x) >>= f = f x

わかりました、これが実際にモナドの法則に従っているとは思いませんが、十分に近いものです。これを使用して、関数を定義できます

srnf = Strict . rnf 

そのような

instance NFData a => NFData (Seq a) where
  rnf s = fromStrict $ (mapM srnf s) >> return ()

テストされていませんが、動作するはずです (すべてのTraversableデータ構造で動作するはずです)。

于 2012-12-20T03:04:50.793 に答える
1

長さを計算するだけでは不十分です。シーケンスのコンテンツの正規形を計算する必要があります。折り畳み可能な構造を強制できるseqFoldableを使用することをお勧めします。Control.Seq次に、簡単に呼び出すことができます

mySeq `using` seqFoldable rdeepseq

または定義する

instance NFData a => NFData (Seq a) where
    rnf = seqFoldable rdeepseq
于 2012-12-21T07:23:26.357 に答える