最近私はライターモナードと遊んでいましたが、スペースリークと思われるものが に入ってしまいました。これらのことをまだ完全に理解しているとは言い難いので、ここで何が起こっているのか、またそれを修正する方法を知りたいと思います。スペースリークとライターとサム(
まず、ここで私はこのエラーを引き起こすことができる方法は次のとおりです。
import Control.Monad.Writer
import Data.Monoid
foo :: Integer -> Writer (Sum Integer) Integer
foo 0 = return 0
foo x = tell (Sum x) >> foo (pred x)
main = print $ runWriter $ foo 1000000
私が手:
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase it.
は、これをよりよく理解するために、私はライターや和せずに同様の機能 を再実装し、もししました私は物事を素敵で怠惰に保ちますが、私は 同じエラーを受け取ります:
bar :: Integer -> (Integer, Integer)
bar x = bar' 0 x
where bar' c 0 = (0, c)
bar' c x = bar' (c + x) (pred x)
しかし、私は式にseq
を追加することによってこの問題を解決することができます:私は私のfoo
機能のseq
INGの様々なビットを試してみたが、それは助けるために を思えません
bar' c x = c `seq` bar' (c + x) (pred x)
。また、私はControl.Monad.Writer.Strict
を使ってみましたが、 でも違いはありません。
Sum
は何とか厳密にする必要がありますか?または、私は何かが欠けている 全く異なる?
ノート
- 私はここに私の専門用語が間違っていてもよいです。 Space leak zooによれば、私の問題は「スタックオーバーフロー」に分類され、 の場合、どのようにしてより反復的なスタイルに変換するのですか?
foo
私のマニュアル 再帰は問題ですか? - Haskell Space Overflowを読んだ後、
-O2
とコンパイルするアイデアは、ちょうど何が起こるかを見るために でした。これは の別の質問ですが、最適化を使用すると、seq
のdbar
機能さえ実行できません。 更新:-fno-full-laziness
を追加するとこの問題は解決します。厳密ライターモナドのソースで
'Sum'は' newtype'なので、それは根本的な型と同じくらい厳密か怠惰です。 – hammar