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

计算长度是不够的,你需要计算一个序列内容的范式。我建议您使用seqFoldableControl.Seq它允许您强制任何可折叠结构。然后你可以简单地打电话

mySeq `using` seqFoldable rdeepseq

或定义

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

您可以为严格定义一个 monad

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