Как заставить строгую оценку последовательности 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 ответа

Вы можете определить монаду для строгости

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 структуры данных).

Вычислительной длины недостаточно, вам нужно вычислить нормальные формы содержимого последовательности. Я предлагаю вам использовать seqFoldable из Control.Seq что позволяет заставить любую складную конструкцию. Тогда вы можете просто позвонить

mySeq `using` seqFoldable rdeepseq

или определить

instance NFData a => NFData (Seq a) where
    rnf = seqFoldable rdeepseq
Другие вопросы по тегам