Haskell:monad-loggerはロッギングで使うべきか?

またエラー処理とロギングの注意点、Debug.Trace(trace)。
1
あいや🐕 @public_ai000ya

module Foo where import Prelude hidden (色々) type LoggerIO a = LoggerT IO a putStrLn = liftIO Prelude.putStrLn とかした方が良いのかなあ。

2016-09-17 01:37:38
あいや🐕 @public_ai000ya

@Mizunashi_Mana 前提としてmain以下の任意の場所にLoggingTを導入したくて、 main = runStdoutLoggingT mainWithLogging mainWithLogging :: LoggingT IO () とかすると

2016-09-17 01:55:24
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya うーんと話の途中だと思うんですが、そもそも聞きたいのが、それってtoy appの話ですか?実際のプロダクションプロジェクトの話ですか?

2016-09-17 01:57:15
あいや🐕 @public_ai000ya

@Mizunashi_Mana mainWithLogging以下で今までputStrLnしていたコードは全て liftIO putStrLnかlift putStrLnになるはずだと思っていて

2016-09-17 01:56:42
あいや🐕 @public_ai000ya

@Mizunashi_Mana ならばそもそもputStrLn :: String -> LoggingT IO () にしちゃった方がいいのかなー…とか思ってました :(

2016-09-17 01:57:07
あいや🐕 @public_ai000ya

@Mizunashi_Mana 趣味の方です。 (実際のプロダクトだと何か変わったりするのかも気になります)

2016-09-17 01:58:19
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya このlogging使うのって主にログを分かりやすく吐かせるためですか?

2016-09-17 02:02:32
あいや🐕 @public_ai000ya

@Mizunashi_Mana はい。 というのもあまり僕がHaskellのログ周りに詳しくないので選択肢がこれとWriterくらいしかわからなかったのと、 どちらかならばユースケース的にLoggingTかなーと思ったので。

2016-09-17 02:05:24
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya うーん、例えば分りやすいログが出したいなら、putStrLnに[Debug]みたいなプレフィックスを付けたIOの関数作ればいいですし、エラーの情報収集がしたいならcatchを使えばいいです

2016-09-17 02:08:33
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya 主にHaskellではMonadTransを使う場合、プロジェクトで使うでかい複合モナドをプログラムに渡し、各プログラムの関数は型制約によって修飾することで依存を切り離すみたいな書き方をする場合が多く

2016-09-17 02:10:26
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya Loggerが必要な関数はMonadLoggerで修飾する感じになります。そして、それらをまとめた関数にLoggerTを融合させたMonadインスタンスを渡すんですが、実際にロガーが必要な箇所って結構限られます

2016-09-17 02:12:06
あいや🐕 @public_ai000ya

@Mizunashi_Mana ああそっか…、なんか迷走してました。 うわわああああ、助かりました!!

2016-09-17 02:12:48
あいや🐕 @public_ai000ya

迷走してた…。 僕が求めてたのは、IO + WriterTだった気がする。

2016-09-17 02:13:16
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya また、ロガーはプロジェクトによってファイルとstdin両方に出す必要もあれば、どっかにhttpで飛ばすみたいな必要もあるので、結構プロダクションではLoggingTをそのまま使う感じではなかったりする場合もあります

2016-09-17 02:15:34
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya あと、デバッグで純粋関数のトレースがしたい場合はDebug.traceとかも使えます。あとは、トレースデータ自体をHaskell上で操作したいことがあってそういう場合は、IOより純粋な方が便利なのでWriterなども使えます

2016-09-17 02:19:08
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya なので、monad-loggerは完全にプロダクション用途な感じで、カスタムする必要があればカスタムできる、レベル制御のロガーを提供してくれるもので、普通ファイル出力とかを行うのが前提なのでMonadIOを修飾する感じになっています

2016-09-17 02:22:19
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya ということで長々になってしまいましたがとにかく 1. プロダクション用途 2. 色々な実装を考慮している(カスタマイズが前提) 3. 前提がIO向け なのがmonad-loggerなので、toy appにはちょっと向かないかもです

2016-09-17 02:25:15
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya それから、プロダクションではロガーとエラー処理+デバッグの概念は完全に別で、普通純粋関数はテストによってある程度保障されていますし、関数度にエラーを監視したりするとリソース管理が壊れてしまう場合があります

2016-09-17 02:28:47
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya 例えば、エラーログのためにcatchをしてまたthrowするという行為ではもしかしたら、そのエラーをcatchした場面でなんらかのリソース解放処理が必要だったかもしれないのに忘れているみたいな場合が多いです

2016-09-17 02:30:16
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya そのため、ロガーは「プログラムが今一体何をしているのか」、「プログラムが今一体何をしたのか」的な情報をユーザーに分かるようにする機構であって、デバッグにはテストの機構やDebug.trace、エラー処理はエラー処理みたいに分けるのが普通です

2016-09-17 02:32:46
水無麻那 @me@ff.mizunashi.work @Mizunashi_Mana

@public_ai000ya デバッグのためにロガーを利用するのでなく、ロガーのためにエラー処理をするのでなく、みたいな感じです。もちろんエラー処理の時に「エラー処理の状況を伝える」ためにロガーを使うのは大丈夫ですが、プロダクションではそんな感じの使い分けをします

2016-09-17 02:33:50
あいや🐕 @public_ai000ya

@Mizunashi_Mana うおお、こんなにわかりやすくいっぱいありがとうございます!(僕の実力故、具体的にイメージできてない箇所はありますが…)

2016-09-17 02:30:17