我有以下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)
因此,我计算序列的长度以强制评估序列本身。这似乎有效,但这是正确的实现吗?还有更好的吗?计算序列的长度是否会引入太多的开销?
答案 0 :(得分:1)
您可以为严格性定义monad
data Strict a = Strict {fromStrict :: !a}
instance Monad Strict where
return = Strict
(Strict x) >>= f = f x
好吧,我不认为这实际上遵守了monad法则,但它足够接近。使用它你可以定义一个函数
srnf = Strict . rnf
这样
instance NFData a => NFData (Seq a) where
rnf s = fromStrict $ (mapM srnf s) >> return ()
未经测试,但应该有效(并且它应该适用于所有Traversable
数据结构)。
答案 1 :(得分:1)
计算长度不够,您需要计算序列内容的正常形式。我建议您使用Control.Seq
中的seqFoldable,它允许您强制使用任何可折叠结构。然后你可以简单地打电话
mySeq `using` seqFoldable rdeepseq
或定义
instance NFData a => NFData (Seq a) where
rnf = seqFoldable rdeepseq