问题
I have the following Haskell type definition:
import Data.Sequence(Seq, length)
import Data.ByteString.UTF8(ByteString)
type StringSeq = Seq ByteString
I have expressions of type StringSeq
for which I would like to force strict evaluation with deepseq
. So I need to define instances of NFData
. I did the following:
import Control.DeepSeq(NFData, deepseq)
instance NFData ByteString
instance NFData a => NFData (Seq a) where
rnf s = rnf (length s)
So I compute the length of a sequence to force evaluation of the sequence itself. This seems to work but is this the correct implementation? Are there better ones? Does computing the length of a sequence introduce too much overhead?
回答1:
You can define a monad for strictness
data Strict a = Strict {fromStrict :: !a}
instance Monad Strict where
return = Strict
(Strict x) >>= f = f x
Okay, I don't think this actually obeys the monad laws, but it is close enough. Using this you can define a function
srnf = Strict . rnf
such that
instance NFData a => NFData (Seq a) where
rnf s = fromStrict $ (mapM srnf s) >> return ()
Untested, but should work (and it should work for all Traversable
data structures).
回答2:
Computing length is not enough, you need to compute the normal forms of the content of a sequence. I suggest you to use seqFoldable from Control.Seq
which allows you to force any foldable structure. Then you can call simply
mySeq `using` seqFoldable rdeepseq
or define
instance NFData a => NFData (Seq a) where
rnf = seqFoldable rdeepseq
来源:https://stackoverflow.com/questions/13963102/how-to-force-strict-evaluation-of-a-sequence-of-bytestring