모나드와 동형 인 다음 모나드를 고려하십시오 (Bool ->)
.
data Pair a = P a a
instance Functor Pair where
fmap f (P x y) = P (f x) (f y)
instance Monad Pair where
return x = P x x
P a b >>= f = P x y
where P x _ = f a
P _ y = f b
Maybe
모나드로 구성합니다 .
newtype Bad a = B (Maybe (Pair a))
나는 그것이 Bad
모나드가 될 수 없다고 주장합니다 .
부분 증명 :
다음 fmap
을 충족시키는 정의 하는 방법은 하나뿐입니다 fmap id = id
.
instance Functor Bad where
fmap f (B x) = B $ fmap (fmap f) x
모나드 법칙을 상기하십시오.
(1) join (return x) = x
(2) join (fmap return x) = x
(3) join (join x) = join (fmap join x)
의 정의 return x
에는 두 가지 선택이 있습니다. B Nothing
또는 B (Just (P x x))
. x
(1)과 (2)에서 돌아올 희망을 가지려면 버릴 수 없으므로 x
두 번째 옵션을 선택해야합니다.
return' :: a -> Bad a
return' x = B (Just (P x x))
그게 떠난다 join
. 가능한 입력이 적기 때문에 각각에 대해 케이스를 만들 수 있습니다.
join :: Bad (Bad a) -> Bad a
(A) join (B Nothing) = ???
(B) join (B (Just (P (B Nothing) (B Nothing)))) = ???
(C) join (B (Just (P (B (Just (P x1 x2))) (B Nothing)))) = ???
(D) join (B (Just (P (B Nothing) (B (Just (P x1 x2)))))) = ???
(E) join (B (Just (P (B (Just (P x1 x2))) (B (Just (P x3 x4)))))) = ???
출력 형식을 갖기 때문에 Bad a
, 유일한 옵션은 B Nothing
또는 B (Just (P y1 y2))
여기서 y1
, y2
로부터 선택되어야한다 x1 ... x4
.
(A)와 (B)의 경우에는 type 값이 없으므로 두 경우 모두 a
반환해야합니다 B Nothing
.
사례 (E)는 (1) 및 (2) 모나드 법칙에 의해 결정됩니다.
join (return' (B (Just (P y1 y2))))
=
join (B (Just (P (B (Just (P y1 y2))) (B (Just (P y1 y2))))))
=
B (Just (P y1 y2))
반환하기 위해 B (Just (P y1 y2))
케이스 (E)에서,이 방법은 우리가 선택해야 y1
하나에서 x1
나 x3
, 그리고 y2
에서 하나 x2
또는 x4
.
join (fmap return' (B (Just (P y1 y2))))
=
join (B (Just (P (return y1) (return y2))))
=
join (B (Just (P (B (Just (P y1 y1))) (B (Just (P y2 y2))))))
=
B (Just (P y1 y2))
마찬가지로, 이것은 우리가 선택해야한다고 말한다 y1
하나에서 x1
나 x2
, 그리고 y2
에서 하나 x3
또는 x4
. 두 가지를 결합하여 (E)의 오른쪽이이어야 함을 결정합니다 B (Just (P x1 x4))
.
지금까지는 모두 좋지만 (C)와 (D)의 오른쪽을 채우려 고 할 때 문제가 발생합니다.
각각에 대해 5 개의 가능한 오른편이 있으며 어떤 조합도 작동하지 않습니다. 아직 이에 대한 좋은 주장은 없지만 모든 조합을 철저히 테스트하는 프로그램이 있습니다.
{-# LANGUAGE ImpredicativeTypes, ScopedTypeVariables #-}
import Control.Monad (guard)
data Pair a = P a a
deriving (Eq, Show)
instance Functor Pair where
fmap f (P x y) = P (f x) (f y)
instance Monad Pair where
return x = P x x
P a b >>= f = P x y
where P x _ = f a
P _ y = f b
newtype Bad a = B (Maybe (Pair a))
deriving (Eq, Show)
instance Functor Bad where
fmap f (B x) = B $ fmap (fmap f) x
unit :: a -> Bad a
unit x = B (Just (P x x))
joins :: Integer
joins = sum $ do
let ways = [ \_ _ -> B Nothing
, \a b -> B (Just (P a a))
, \a b -> B (Just (P a b))
, \a b -> B (Just (P b a))
, \a b -> B (Just (P b b)) ] :: [forall a. a -> a -> Bad a]
c3 :: forall a. a -> a -> Bad a <- ways
c4 :: forall a. a -> a -> Bad a <- ways
let join :: forall a. Bad (Bad a) -> Bad a
join (B Nothing) = B Nothing
join (B (Just (P (B Nothing) (B Nothing)))) = B Nothing
join (B (Just (P (B (Just (P x1 x2))) (B Nothing)))) = c3 x1 x2
join (B (Just (P (B Nothing) (B (Just (P x3 x4)))))) = c4 x3 x4
join (B (Just (P (B (Just (P x1 x2))) (B (Just (P x3 x4)))))) = B (Just (P x1 x4))
guard $ all (\x -> join (unit x) == x) bad1
guard $ all (\x -> join (fmap unit x) == x) bad1
guard $ all (\x -> join (join x) == join (fmap join x)) bad3
return 1
main = putStrLn $ show joins ++ " combinations work."
bad1 :: [Bad Int]
bad1 = map fst (bad1' 1)
bad3 :: [Bad (Bad (Bad Int))]
bad3 = map fst (bad3' 1)
bad1' :: Int -> [(Bad Int, Int)]
bad1' n = [(B Nothing, n), (B (Just (P n (n+1))), n+2)]
bad2' :: Int -> [(Bad (Bad Int), Int)]
bad2' n = (B Nothing, n) : do
(x, n') <- bad1' n
(y, n'') <- bad1' n'
return (B (Just (P x y)), n'')
bad3' :: Int -> [(Bad (Bad (Bad Int)), Int)]
bad3' n = (B Nothing, n) : do
(x, n') <- bad2' n
(y, n'') <- bad2' n'
return (B (Just (P x y)), n'')
join
두 개의 모나드 구성에 대해 작성하는 것이 불가능 함을 보여줍니다 . 일반 . 그러나 이것은 구체적인 예로 이어지지 않습니다 .