モナド則1(左単位元)を満たさない偽リストモナド
import Monad(liftM) data MyList a = My { unMy :: [a] } deriving (Show,Eq) instance Monad MyList where return x = My [x,x] (My xs) >>= k = My $ xs >>= (unMy.k) -- sample f x = My [x,x+1]
とすると
> return 2 >>= f My {unMy = [2,3,2,3]} > f 2 My {unMy = [2,3]}
のようにモナド則1(左単位元)が成り立ちません。(モナド則2(右単位元)も成り立っていませんが今回はモナド則1の方にだけ注目します)
モナド則1を満たせば例えば次のコード
do x <- My [1,2] f (2*x)
は
do x <- My [1,2] return (2*x) >>= f
と変形でき、この前半部に Monadモジュールの liftM を使ってさらに
liftM (2*) (My [1,2]) >>= f
と変形することができます。
しかし今回の例ではモナド則1が成り立っていませんから上記の書き換えを行なうと違う計算になってしまいます。
実際
> do {x <- My [1,2]; f (2*x)} My {unMy = [2,3,4,5]} > liftM (2*) (My [1,2]) >>= f My {unMy = [2,3,2,3,4,5,4,5]}
のように結果が違ってきます。
このようにモナド則1が成り立たないと liftM のような関数を使った書き換えを行なうことができなくなります。(他にも内部で return を使っている便利な関数はたくさんあります)