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