Alternative, MonadPlus (LeftCatch) ve MonadPlus (LeftDistributive) arasındaki ilişkiler nelerdir?


12

Takip Etme MonadPlus olmayan ancak alternatif olan bir Monad örneği nedir? :

Varsayalım bir tek hücreli olup. İlişkiler betweem nelerdir m bir varlık Alternatif bir MonadPlusCatch ve MonadPlusDistr ? mmAltı olası çiftin her biri için ya birinin diğerini ima ettiğine dair bir kanıt ya da buna karşı olmayan bir karşı örnek istiyorum.

(Kullanıyorum

  • MonadPlusCatch bir ayırt etmek MonadPlus o karşılar Sol Yakalama kuralı:

    mplus (return a) b = return a
    
  • MonadPlusDistr bir ayırt etmek MonadPlus satifies o Sol Dağıtım kuralı:

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

HaskellWiki'deki MonadPlus'a bakınız .)


Mevcut bilgim + sezgim şudur:

  1. MonadPlusDist Alternatif - muhtemelen doğru - basit görünüyor, bir kanıt taslağım olduğuna inanıyorum, kontrol edeceğim ve eğer doğruysa, AndrewC bu bölümü yanıtladı.
  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)
    

    tekrar kontrol edip yayınlayacağım. (İlginçtir, sadece için Maybebiz eğer analiz edebilirsiniz, çünkü kanıtlanabilir olduğunu aolduğunu Just somethingveya Nothing-. Yukarıda belirtilen AndrewC cevabını bakınız)

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

Yanıtlar:


8

(çünkü Petr Pudlák'ın işaret ettiği gibi [], bir karşı örnek - MonadPlusCatch'i tatmin etmiyor , ancak MonadPlusDist'i tatmin ediyor , dolayısıyla Uygulayıcı )

Varsayılan: MonadPlusDist Yasaları

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

Kanıtlamak için: Alternatif Kanunlar

-- ((<|>),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

<*>genişleme lemması
Bir monadın bir uygulamasının standart türevini kullandığımızı varsayalım, (<*>) = apve pure = return. Sonra

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

Çünkü

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)

<$>genişleme lemması
Bir monaddan bir fonksiyonlayıcının standart türevini kullandığımızı varsayalım (<$>) = liftM. Sonra

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

Çünkü

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 

Kanıt

MonadPlus yasalarını karşıladığını varsayalım ( <+>, m0). Önemsiz o zaman bir monoid.

Sağ Fark <*>

Kanıtlayacağım

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

çünkü gösterimde daha kolay.

(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

Sol Kimlik <*>

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

gereğince, gerektiği gibi.

Sol Fark <$>

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 >>=

gereğince, gerektiği gibi


1
Harika. Hatta herhangi bir Başvuru Sahibi için sol yasaların doğru yasalar tarafından ima edildiğinden bile şüpheleniyorum , ancak şimdiye kadar kanıtım yok. Sezgi, f <$>herhangi bir deyimsel hareket taşımadığı, saf olduğu için bir şekilde "yanları değiştirmek" mümkün olabilir.
Petr Pudlák

@ PetrPudlák Güncellendi - kanıtı tamamladı ve corollory'yi ekledi [].
AndrewC

@ PetrPudlák Sizce MonadPlusCatch'i[] tatmin eden bir kanıt eklememiz gerekiyor mu? Şu anda HaskellWiki'de sadece bir iddia. >>= kfoldr ((++).k)
AndrewC

Sanırım MonadPlusDist demek istiyorsun , değil mi? Bence başarabiliriz, bu sonucun kanıtını tamamlardı.
Petr Pudlák

@ PetrPudlák Oh evet, üzgünüm. Yapacağım.
AndrewC

6

Gerçekten de 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)
       )

Çıktı

(Right Nothing, Left "something")

yani MaybeT Eithersol dağıtım yasası başarısız olur Applicative.


Sebebi şu ki

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

g( LeftCatch nedeniyle ) yok sayar ve yalnızca

return x `ap` a

ancak bu diğer tarafın değerlendirdiğinden farklıdır:

g `ap` a
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.