したがって、次のようになります。
import Control.Monad.Writer.Strict
type M a = Writer (Map Key Val) a
いくつかのKey
とVal
。
収集された出力を見ない限り、すべて問題なく動作します。
report comp = do
let (a,w) = runWriter comp
putStrLn a
ただし、 を調べたい場合はw
、スタック オーバーフローが発生します。
report comp = do
let (a,w) = runWriter comp
guard (not $ null w) $ do -- forcing w causes a stack overflow
reportOutputs w
putStrLn a
(>>=)
その理由は、 forWriter
が次のように定義されているためだと思います。
m >>= k = WriterT $ do
(a, w) <- runWriterT m
(b, w') <- runWriterT (k a)
return (b, w `mappend` w')
大規模なWriter a
計算を行うと、長い一連の mappend が作成されます。w <> (w' <> (w'' <> ...))
この場合、Map.union
これはマップの背骨で厳密な a です。したがって、ユニオンの大きなシーケンスを構築する場合、スタックをオーバーフローする Map を強制するとすぐに、すべてを評価する必要があります。
私たちが望むのは、結合を早期に実行することです。より厳密な Strict.Writer が必要です。
m >>= k = WriterT $ do
(a, w) <- runWriterT m
(b, w') <- runWriterT (k a)
let w'' = w `mappend` w'
w'' `seq` return (b, w'')
だから私の質問は:これはいくつかの「標準」ライブラリに存在しますか? そうでない場合、なぜですか?