Writerモナド
なので、Stringに限らずモノイドのインスタンスであればなんでも良い感じに扱える
MaybeがJustかNothingかの文脈を持ち回るように、Writerモナドではログの文字列を持ち回り、ログをするタイミングで今まで持っていたログに追記して持ち回る感じ
型の定義
code:hs
newtype Writer w a = Writer { runWriter :: (a, w) }
wが主の型
これがStringならログっぽい使い方ができる
定義
code:hs
instance (Monoid w) => Monad (Writer w) where
return x = Writer (x, mempty)
(Writer (x, v)) >>= f = let (Writer (y, v')) = f x
in Writer (y, v <> v')
>>=では、f xの中身を取り出して、元のvと連結したv <> v'とyを返している
methods
tell :: MonadWriter w m => w -> m ()
状態aに追記するアクション
writer :: MonadWriter w m => (a, w) -> m a
普通のタプルからWriter型を作成する
関数
runWriter :: Writer w a -> (a, w)
Writer型の中身のタプルを返す
runStateでは初期状態として()を渡すが、writerStateでは初期状態は空なので何も渡さなくていい
code:hs
import Control.Monad.Writer
main = do
print $ runWriter $ do -- 初期値はいらない
tell "a"
tell "b"
tell "c"
return ()
-- ((),"abc")
execWriter :: Writer w a -> w
状態だけを返す
動く用いた具体例
ref すごいH本.icon p.322
code:hs
import Control.Monad.Writer
logNum :: Int -> Writer String Int multWithLog :: Writer String Int multWithLog = do
a <- logNum 3
b <- logNum 5
return $ a * b
-- > runWriter multWithLog
用途
ログを取るとか
注意
Writerモナド内のモノイドの連結が左結合にならないように注意する
ref すごいH本.icon p.325
追記するだけで途中で読むことはできない?
参考