Я пытаюсь преобразовать монаду Data.Binary.PutM в преобразователь монад. Поэтому я начал с изменения его определения с
newtype PutM a = Put { unPut :: PairS a }
на
newtype PutM a = Put { unPut :: Identity (PairS a) }
. Затем, конечно, я изменил реализации функций return и >> = :
From:
return a = Put $ PairS a mempty
{-# INLINE return #-}
m >>= k = Put $
let PairS a w = unPut m
PairS b w1 = unPut (k a)
in PairS b (w `mappend` w1)
{-# INLINE (>>=) #-}
m >> k = Put $
let PairS _ w = unPut m
PairS b w1 = unPut k
in PairS b (w `mappend` w1)
{-# INLINE (>>) #-}
Кому:
return a = Put $! return $! PairS a mempty
{-# INLINE return #-}
m >>= k = Put $!
do PairS a w <- unPut m
PairS b w1 <- unPut (k a)
return $! PairS b $! (w `mappend` w1)
{-# INLINE (>>=) #-}
m >> k = Put $!
do PairS _ w <- unPut m
PairS b w1 <- unPut k
return $! PairS b $! (w `mappend` w1)
{-# INLINE (>>) #-}
Как будто монада PutM была просто монадой Writer. К сожалению, это ( снова ) привело к утечке места. Мне ясно (или это так?), Что ghc где-то откладывает оценку, но я попытался разместить везде $!
вместо $
, как было предложено в некоторых руководствах, но это не помогло . Кроме того, я не уверен, насколько полезен профилировщик памяти, если он показывает мне следующее:
.
И для полноты, это профиль памяти, который я получаю при использовании исходной монады Data.Binary.Put:
Если интересно, здесь - это код, который я использую для его тестирования, и строка, которую я использую для компиляции , запустите и создайте профиль памяти:
ghc -auto-all -fforce-recomp -O2 --make test5.hs && ./test5 +RTS -hT && hp2ps -c test5.hp && okular test5.ps
Надеюсь, я никого не раздражаю своей сагой об утечках памяти. Я обнаружил, что в Интернете не так много хороших ресурсов по этой теме, что оставляет новичка в неведении.
Спасибо за внимание.