私はData.Binary.Putモナドを別のものにラップしようとしていますので、後で "書き込むバイト数"や "ファイルの現在の位置"などの質問をすることができます。しかし、のようにも非常に些細なラップ:なぜData.Binary.Putモナドをラップするとメモリリークが発生するのですか?
data Writer1M a = Writer1M { write :: P.PutM a }
or
data Writer2M a = Writer2M { write :: (a, P.Put) }
は、巨大な宇宙漏れやプログラムを作成し、通常は(4GBのRAMを取った後)がクラッシュします。
-- 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のに新たなんだ、これは私に何のローミングサービスを行うものではありませんが、ラッパーモナドは非常に些細なように見えるので、私はそこに推測している:ここで私はこれまで試したものです私は行方不明です。
ありがとうございます。
UPDATE:http://hpaste.org/43400/why_wrapping_the_databinaryp
アップデート2: この質問hereへの第二の部分もあり ここでは、問題を示すサンプルコードです。
どのコンパイラフラグを使用していますか? –
あなたが質問したところで、私は-O2で試しましたが(私は以前は使っていませんでしたが)メモリのフットプリントは変わりませんでした。 –
簡単なテストプログラムを投稿して、他の人が自分でビルドする必要はありませんか? –