WriterでもControl.Monad.Trans.Writer.CPSは典型的なスペースリークはしない
Writerを使いたいけどスペースリークが怖い
Writerを使ってはならない - Qiita に書かれているように、 HaskellのWriterは長年スペースリークの元になるので敬遠されてきました。
しかし、私はWriterのインターフェイスをとても使いたいのでもやもやしていました。
ReaderT パターン(翻訳) - LugendrePublic ではスペースリークの危険性があってもWriter使った方が早かったから使ってると書いてありましたが、それでもスペースリークの危険性を考えながら書くのはなんだか気がひけます。
Control.Monad.Trans.Writer.CPS という新しいのが出てきましたが、これがスペースリークしないか分からないので困惑していました。
Twitterでこれは問題ないはずと教えてもらいましたが、検索しても文献が見つからずに確信を持てませんでした。
計測すれば良いじゃん
前述の、 Writerを使ってはならない - Qiita で計測されているコードをCPS版で実行すれば、少なくともこの問題は存在するか簡単に分かることに気が付きました。
最初のコードをStrict
をCPS
に書き換えだけして実行しました。
-- print strict writer result
action1
action2
action3
tell1
sum1
tell2
sum2
tell3
sum3
value3
value2
value1
4
-- print strict writer log
Sum {getSum = 6}
sumが途中で出力されているので、途中で評価されていることが分かりました。
ソースコードを見ても途中でseq
を挟んでいるようです。
これだけで全てのスペースリークに対する問題が解決したと分かったわけではありませんが、典型的なスペースリークはしないようですね。
RIO.Writerも大丈夫(ではない)
RIO.Writer
も最終的にControl.Monad.Trans.Writer.CPS
をexportしているので同様に問題ありません。
追記: 危険。2022-12-24に確認した所、Lazyをexportしていることが分かりました
この記事を書いた時はCPS版をexportしていると思ったみたいですが、よくよく確認してみるとLazy版をexportしていました。危険なので別途importする必要があるでしょう。