generated at
モナド則
monad law
Monad型クラスのインスタンスとなる型が満たすべき条件
Monad型クラスのインスタンスになるだけでは本物のモナドとは呼べない
ただし、型クラスの実装に関してはコンパイラはチェックしてくれるが、モナド則を満たしているかどうかはチェックしてくれない
自力でチェックする必要がある
標準で入っているモナドは満たしている(はず)
Agda, Idris, Coqあたりの言語では外部ライブラリを用いてモナドが使え、モナド則もチェックしてくれるらしい

前提
出てくるものの型
m Monad 型クラスの型
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 \equiv f x
<=< >=> を使って書き直すと
こっちが本質な気がするmrsekut
f <=< return \equiv f
return >=> f \equiv f
2. 右恒等性
return が bind の右側単位元になっている
m >>= return \equiv m
>>= return はモナド値に対する恒等射
<=< >=> を使って書き直すと
こっちが本質な気がするmrsekut
return <=< f \equiv f
f >=> return \equiv f
3. bind の結合則
以下の等式が成り立つ
m >>= f >>= g \equiv m >>= (\x -> f x >>= g)
連続のbindを、ラムダ関数とbindを使って書き直している
要するにモナド関数の結合法則が成り立つことを言っている
こっちが本質な気がするmrsekut
((f >>= g) >>= h) \equiv (f >>= (g >>= h))
((f <=< g) <=< h) \equiv (f <=< (g <=< h))
(f >=> g) >=> h \equiv f >=> (g >=> h)
完全に理解できていないのですごいH本 p.311読み直そう


bindの向きを逆にしたもの
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で見てみる
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で見てみる
hs
f :: Int -> [Int] f x = [x, x, x] return 3 >>= f -- [3,3,3] [3] >>= f -- [3,3,3] f 3 -- [3,3,3]
2の右恒等性を見てみる
hs
-- List [1,2,3] >>= return -- [1,2,3] -- Maybe Just 3 >>= return -- Just 3 Nothing >>= return -- Nothing



モノイド則、通常の関数との対応
モナド則.hs
return >=> f == f -- 左恒等性 f >=> return == f -- 右恒等性 (f >=> g) >=> h == f >=> (g >=> h) -- 結合法則
モノイド則.hs
mempty <> a == a -- 左恒等性 a <> mempty == a -- 右恒等性 (a <> b) <> c == a <> (b <> c) -- 結合法則
通常の関数.hs
id . f == f -- 左恒等性 f . id == f -- 右恒等性 (f . g) . h == f . (g . h) -- 結合法則



参考
8.5