Writer Monad

Int as Monoid

整数は加法についてモノイドである*1。Monoidのインスタンスにしてみよう。

instance Monoid Int where
  mempty = 0
  mappend = (+)
sum' :: [Int] -> Int
sum' = mconcat

vecPlus :: (Int, Int) -> (Int, Int) -> (Int, Int)
vecPlus = mappend

Writer Monad

Writer Monad は Monoid に書き足していく。

class (Monoid w, Monad m) => MonadWriter w m | m -> w where

先ほどIntをMonoidにしたことを使って、フィボナッチ数を計算してみる。

fib' n | n < 2 = tell n
fib' n = fib' (n - 1) >> fib' (n - 2) 

fib :: Int -> Int
fib = execWriter . fib'

実際には、Intではなくてログなどの総和*2を求めさせる使いかたが多い。

><

*1:乗法についても

*2:Lazyに