Alternative, MonadPlus (LeftCatch) 및 MonadPlus (LeftDistributive)의 관계는 무엇입니까?


12

다음 은 대안이지만 MonadPlus가 아닌 Monad의 예는 무엇입니까? :

이 모나드라고 가정하십시오 . 관계의의 차이와의 무엇입니까 m 되는 대체 하는 MonadPlusCatchMonadPlusDistr은 ? mm여섯 가지 가능한 쌍 각각에 대해 하나는 다른 것을 의미한다는 증거 또는 그렇지 않은 반례를 갖고 싶습니다.

(사용하고 있습니다

  • 왼쪽 캐치 규칙 을 만족 하는 MonadPlus 를 구별하기위한 MonadPlusCatch :

    mplus (return a) b = return a
    
  • Left-Distribution 규칙 을 만족 시키는 MonadPlus 를 구별하기위한 MonadPlusDistr :

    mplus a b >>= k = mplus (a >>= k) (b >>= k)
    

참조 HaskellWiki에 MonadPlus를 .)


나의 현재 지식 + 직관은 :

  1. MonadPlusDist 대안 - 사실 일 가능성이 있습니다 - 간단 해 보입니다. 증거의 스케치가 있다고 생각합니다. 확인하고 올 바르면 AndrewC가이 부분에 답변했다고 게시하겠습니다 .
  2. Maybe
  3. MaybeT (Either e)MaybeT m'

    ((pure x) <|> g) <*> a =    -- LeftCatch
        (pure x) <*> a
    -- which in general cannot be equal to
    ((pure x) <*> a) <|> (g <*> a)
    

    다시 확인하고 게시하겠습니다. (흥미롭게도, 단지에 대해 Maybe우리가 경우에 분석 할 수 있기 때문에, 증명의 a이다 Just something또는 Nothing-. 상기 AndrewC의 답변을 참조)

  4. [][]
  5. []
  6. Maybe

답변:


8

(Petr Pudlák이 지적했듯이 []반례입니다 -MonadPlusCatch를 만족 시키지 않지만 MonadPlusDist를 만족시키지 않으므로 Applicative )

가정 : MonadPlusDist 법칙

-- (mplus,mzero) is a monoid
mzero >>= k = mzero`                             -- left identity >>=
(a `mplus` b) >>= k  =  (a >>=k) `mplus` (b>>=k) -- left dist mplus

증명하기 위해 : 대체 법

-- ((<|>),empty) is a monoid
(f <|> g) <*> a = (f <*> a) <|> (g <*> a) -- right dist <*>
empty <*> a = empty                       -- left identity <*>
f <$> (a <|> b) = (f <$> a) <|> (f <$> b) -- left dist <$>
f <$> empty = empty                       -- empty fmap

<*>확장 표제어
우리 즉 모나드에서 실용적 표준 유도를 사용한다고 가정 (<*>) = ap하고 pure = return. 그때

mf <*> mx = mf >>= \f -> mx >>= \x -> return (f x)

때문에

mf <*> mx = ap mf mx                                  -- premise
          = liftM2 id mf mx                           -- def(ap)
          = do { f <- mf; x <- mx; return (id f x) }  -- def(liftM2)
          = mf >>= \f -> mx >>= \x -> return (id f x) -- desugaring
          = mf >>= \f -> mx >>= \x -> return (f x)    -- def(id)

<$>expansion lemma
모나드에서 펑터의 표준 파생을 사용한다고 가정하자 (<$>) = liftM. 그때

f <$> mx = mx >>= return . f

때문에

f <$> mx = liftM f mx                    -- premise
         = do { x <- mx; return (f x) }  -- def(liftM)
         = mx >>= \x -> return (f x)     -- desugaring
         = mx >>= \x -> (return.f) x     -- def((.))
         = mx >>= return.f               -- eta-reduction 

증명

( <+>, m0)가 MonadPlus 법률을 충족 한다고 가정합니다 . 사소한 일입니다.

오른쪽 디스트 <*>

증명 할게

(mf <+> mg) <*> ma = (mf <*> ma) <+> (mg <*> ma) -- right dist <*>

표기법이 더 쉽기 때문입니다.

(mf <+> mg) <*> ma = (mf <+> mg) >>= \forg -> mx >>= \x -> return (forg x) -- <*> expansion
                   =     (mf >>= \f_g -> mx >>= \x -> return (f_g x))
                     <+> (mg >>= \f_g -> mx >>= \x -> return (f_g x))      -- left dist mplus
                   = (mf <*> mx) <+> (mg <*> mx)                           -- <*> expansion

왼쪽 정체성 <*>

mzero <*> mx = mzero >>= \f -> mx >>= \x -> return (f x) -- <*> expansion
             = mzero                                     -- left identity >>=

필요에 따라.

왼쪽 디스트 <$>

f <$> (a <|> b) = (f <$> a) <|> (f <$> b) -- left dist <$>

f <$> (a <+> b) = (a <+> b) >>= return . f              -- <$> expansion
                = (a >>= return.f) <+> (b >>= return.f) -- left dist mplus
                = (f <$> a) <+> (f <$> b)               -- <$> expansion

empty fmap

f <$> mzero = mzero >>= return.f   -- <$> expansion
            = mzero                -- left identity >>=

필요에 따라


1
큰. 나는 심지어 좌법이 어떤 응용 에 대한 우법에도 내포되어 있다고 의심 하지만, 지금까지 아무런 증거도 없다. 직관은 f <$>관용적 행동을 수행하지 않으며, 순수하기 때문에 어떻게 든 "측면 전환"이 가능할 수 있습니다.
Petr Pudlák

@ PetrPudlák 업데이트-완성 된 증명과에 대한 귀하의 목록을 추가했습니다 [].
AndrewC

@ PetrPudlák MonadPlusCatch를 []만족시키는 증거를 추가해야한다고 생각하십니까 ? 현재는 HaskellWiki에 대한 단언 일뿐입니다. >>= k명시 적으로 사용하여 정의한다foldr ((++).k)
AndrewC

나는 당신이 MonadPlusDist 을 의미한다고 가정 합니까? 나는 우리가 할 수 있다고 생각한다. 이것이 계약의 증거를 완성시킬 것이다.
Petr Pudlák

@ PetrPudlák 오 예, 죄송합니다. 할 것이다.
AndrewC

6

실제로 그것은 MaybeT Either:

{-# LANGUAGE FlexibleInstances #-}
import Control.Applicative
import Control.Monad
import Control.Monad.Trans.Maybe

instance (Show a, Show b) => Show (MaybeT (Either b) a) where
    showsPrec _ (MaybeT x) = shows x

main = print $
    let
        x = id :: Int -> Int
        g = MaybeT (Left "something")
        a = MaybeT (Right Nothing)
    -- print the left/right side of the left distribution law of Applicative:
    in ( ((return x) `mplus` g) `ap` a
       , ((return x) `ap` a) `mplus` (g `ap` a)
       )

출력은

(Right Nothing, Left "something")

이는 MaybeT Either의 왼쪽 배포 법에 위배 Applicative됩니다.


그 이유는

(return x `mplus` g) `ap` a

LeftCatchg 로 인해 무시 하고 다음과 같이 평가합니다.

return x `ap` a

그러나 이것은 다른 쪽이 평가하는 것과 다릅니다.

g `ap` a
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.