モナド則
monad law
Monad型クラスのインスタンスになるだけでは本物のモナドとは呼べない ただし、型クラスの実装に関してはコンパイラはチェックしてくれるが、モナド則を満たしているかどうかはチェックしてくれない
自力でチェックする必要がある
標準で入っているモナドは満たしている(はず)
前提
出てくるものの型
mはMonad型クラスの型
code:hs
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
(>=>) :: (a -> m b) -> (b -> m c) -> (a -> m c)
f >=> g = \x -> f x >>= g
f :: a -> m a
1. 左恒等性
return が bind の左側単位元になっている
return x >>= f $ \equivf x
<=<、>=>を使って書き直すと
こっちが本質な気がするmrsekut.icon
f <=< return$ \equivf
return >=> f$ \equivf
2. 右恒等性
return が bind の右側単位元になっている
m >>= return $ \equivm
>>= returnはモナド値に対する恒等射
<=<、>=>を使って書き直すと
こっちが本質な気がするmrsekut.icon
return <=< f$ \equivf
f >=> return$ \equivf
3. bind の結合則
以下の等式が成り立つ
m >>= f >>= g$ \equivm >>= (\x -> f x >>= g)
連続のbindを、ラムダ関数とbindを使って書き直している
要するにモナド関数の結合法則が成り立つことを言っている
こっちが本質な気がするmrsekut.icon
((f >>= g) >>= h)$ \equiv(f >>= (g >>= h))
((f <=< g) <=< h)$ \equiv(f <=< (g <=< h))
(f >=> g) >=> h$ \equivf >=> (g >=> h)
完全に理解できていないのですごいH本.icon p.311読み直そう
bindの向きを逆にしたもの
code:hs
return :: a -> M a
(=<<) :: (a -> M b) -> (M a -> M b)
(=<<) return t = t
(=<<) f (return a) = f a
(=<<) g (((=<<) f) t) = (=<<) (\a -> (=<<) g (f a)) t
具体例
1の左恒等性をMaybeで見てみる
code:hs
f :: Int -> Maybe Int
f x = Just (x+1)
return 3 >>= f -- Just 4
Just 3 >>= f -- Just 4
f x -- Just 4
定義よりMaybeではreturnとJustは同じ
1の左恒等性をListで見てみる
code:hs
2の右恒等性を見てみる
code:hs
-- List
-- Maybe
Just 3 >>= return -- Just 3
Nothing >>= return -- Nothing
code:モナド則.hs
return >=> f == f -- 左恒等性
f >=> return == f -- 右恒等性
(f >=> g) >=> h == f >=> (g >=> h) -- 結合法則
code:モノイド則.hs
mempty <> a == a -- 左恒等性
a <> mempty == a -- 右恒等性
(a <> b) <> c == a <> (b <> c) -- 結合法則
code:通常の関数.hs
id . f == f -- 左恒等性
f . id == f -- 右恒等性
(f . g) . h == f . (g . h) -- 結合法則
参考
8.5