Я пытаюсь обернуть DataBinary.Put монаду в другую, чтобы позже я мог задать ему вопросы типа «сколько байтов он собирается писать» или «что такое текущая позиция в файле». Но даже очень тривиальные обручи нравится:Почему обертывание Data.Binary.Put монады создает утечку памяти?
data Writer1M a = Writer1M { write :: P.PutM a }
or
data Writer2M a = Writer2M { write :: (a, P.Put) }
создать огромную утечку пространства и программа, как правило, выходит из строя (после приема до 4 Гб оперативной памяти). Вот то, что я пытался до сих пор:
-- This works well and consumes almost no memory.
type Writer = P.Put
writer :: P.Put -> Writer
writer put = put
writeToFile :: String -> Writer -> IO()
writeToFile path writer = BL.writeFile path (P.runPut writer)
-- This one will cause memory leak.
data Writer1M a = Writer1M { write :: P.PutM a }
instance Monad Writer1M where
return a = Writer1M $ return a
ma >>= f = Writer1M $ (write ma) >>= \a -> write $ f a
type WriterM = Writer1M
type Writer = WriterM()
writer :: P.Put -> Writer
writer put = Writer1M $ put
writeToFile :: String -> Writer -> IO()
writeToFile path writer = BL.writeFile path (P.runPut $ write writer)
-- This one will crash as well with exactly the
-- same memory foot print as Writer1M
data Writer2M a = Writer2M { write :: (a, P.Put) }
instance Monad Writer2M where
return a = Writer2M $ (a, return())
ma >>= f = Writer2M $ (b, p >> p')
where (a,p) = write ma
(b,p') = write $ f a
type WriterM = Writer2M
type Writer = WriterM()
writer :: P.Put -> Writer
writer put = Writer2M $ ((), put)
writeToFile :: String -> Writer -> IO()
writeToFile path writer = BL.writeFile path (P.runPut $ snd $ write writer)
Я новичок в Haskell, и это не имеет никакого Sence мне, но обертка монада кажется очень тривиальной, так что я угадываю что-то очевидное, я пропал без вести.
Спасибо, что посмотрели.
UPDATE: Вот пример кода, который демонстрирует проблему: http://hpaste.org/43400/why_wrapping_the_databinaryp
UPDATE2: Существует также вторая часть этого вопроса here.
Какие флаги компилятора вы используете? –
После того, как вы спросили, что я попробовал с -O2 (раньше я не использовал его), но печать в памяти не изменилась. –
Не могли бы вы опубликовать тривиальную тестовую программу, чтобы другие здесь не могли создавать свои собственные? –