如何强制严格评估ByteString序列

时间:2012-12-19 23:44:01

标签: haskell sequence strict bytestring

我有以下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)

因此,我计算序列的长度以强制评估序列本身。这似乎有效,但这是正确的实现吗?还有更好的吗?计算序列的长度是否会引入太多的开销?

2 个答案:

答案 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