HaHaHa!(old)

2008-09-28

モナド則を満たすべき理由

モナド則ふたたびに対してコメントしたのですが、うっかりして、コード部分のインデントが崩れてしまったのでここに再掲


型の上では「整合性」が取れているので、「整合性」が取れない例というのは示しにくそうです。

モナド則が「あたり前だ」と感じるということは、モナド則が満たされることを暗黙に期待しているということですよね。つまり、モナド則が満されないないことがあれば、そんなのは役に立たないというか、使い道がなさそうではあります。

モナド則を満さなければ、役に立たない」ことの証明は、私には、うまくできそうにないけど、「モナド則を満たさず、かつ、役に立たない」Monad クラスインスタンスなら意図的に作れます。

data List a = Nil | Cons a (List a)

toPrimList :: List a -> [a]
toPrimList Nil = []
toPrimList (Cons x xs) = x : toPrimList xs

instance Show a => Show (List a) where
  show = show . toPrimList

instance Functor List where
  fmap f Nil         = Nil
  fmap f (Cons x xs) = Cons (f x) (fmap f xs)

instance Monad List where
  return x = Nil                         -- モナド則 2 を満たさない
  l >>= f  = fold append Nil (fmap f l)
     where append Nil         ys = ys    -- (++) 相当
           append (Cons x xs) ys = Cons x (append xs ys)
           fold f z Nil = z              -- foldr 相当
           fold f z (Cons x xs) = f x (fold f z xs)

ps = Cons 1 (Cons 2 Nil)                 -- [1,2] 相当
qs = Cons 'a' (Cons 'b' (Cons 'c' Nil))  -- ['a','b','c'] 相当

sample = do p <- ps
            q <- qs
            return (p,q)

sample の値として期待したいのは [ (p,q) | p <- ps, q <- qs ] すなわち

[(1,'a'),(1,'b'),(1,'c'),(2,'a'),(2,'b'),(2,'c')]

相当の List (Int,Char) 型の値だけれど、このモナドの実装ではそうなっていません。

return の実装を

return x = Cons x Nil

にしてモナド則を満すようにすると sample は期待したい値になります。

kazu-yamamotokazu-yamamoto2008/09/29 13:50山本です。お答え頂き、ありがとうございます。
今回の考察で、モナド則2が重要なのは分りました。できればモナド則3を満たさないとおかしくなる例があると、嬉しいのですが。。。

KailashKailash2012/07/24 01:24That's a mold-breaker. Great tinhking!

kxnthkmqmpkxnthkmqmp2012/07/26 18:097mi5UW <a href="http://hoinevmlwpoz.com/">hoinevmlwpoz</a>