Jakie są relacje między Alternative, MonadPlus (LeftCatch) i MonadPlus (LeftDistributive)?


12

Dalsze działania Jaki jest przykład Monady, która jest alternatywą, ale nie MonadPlus? :

Załóżmy, że to monada. Jakie są stosunki betweem m bycia alternatywą , a MonadPlusCatch i MonadPlusDistr ? mmDla każdej z sześciu możliwych par chciałbym mieć albo dowód, że jedna implikuje drugą, lub kontrprzykład, że tak nie jest.

(Używam

  • MonadPlusCatch, aby wyróżnić MonadPlus, który spełnia regułę Left-Catch :

    mplus (return a) b = return a
    
  • MonadPlusDistr, aby wyróżnić MonadPlus, który spełnia regułę lewostronnej dystrybucji :

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

zobacz MonadPlus na HaskellWiki .)


Moja obecna wiedza + intuicja to:

  1. MonadPlusDist Alternatywna - prawdopodobnie prawdziwa - wydaje się prosta, wierzę, że mam szkic dowodu, sprawdzę go, a jeśli jest poprawny, opublikuję go AndrewC odpowiedział na tę część.
  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)
    

    jeszcze raz sprawdzę i opublikuję. (Co ciekawe, po prostu Maybejest to możliwe do udowodnienia, ponieważ możemy przeanalizować, czy ajest Just somethinglub Nothing- zobacz wyżej wspomnianą odpowiedź AndrewC).

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

Odpowiedzi:


8

(ponieważ, jak zauważył Petr Pudlák, []jest kontrprzykładem - nie spełnia MonadPlusCatch, ale spełnia MonadPlusDist , stąd Applicative )

Założono: prawa MonadPlusDist

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

Aby udowodnić: prawa alternatywne

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

<*>lemat rozszerzenia
Załóżmy, że używamy standardowego wyprowadzenia aplikacji z monady, mianowicie (<*>) = api pure = return. Następnie

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

bo

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)

<$>lemat rozszerzenia
Załóżmy, że używamy standardowego wyprowadzenia funktora z monady, mianowicie (<$>) = liftM. Następnie

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

bo

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 

Dowód

Załóż <+>, że ( , m0) spełniają prawa MonadPlus. Po prostu to monoid.

Right Dist <*>

Udowodnię

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

ponieważ jest to łatwiejsze w notacji.

(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

Lewa tożsamość <*>

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

jako wymagane.

Left Dist <$>

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

jako wymagane


1
Wspaniały. Podejrzewam nawet, że prawa lewe są implikowane przez prawa właściwe dla każdego Wnioskodawcy , ale jak dotąd nie mam na to dowodu. Intuicja polega na tym, że f <$>nie ma żadnego idiomatycznego działania, jest czysta, więc może być możliwe „jakoś zmienić strony”.
Petr Pudlák

@ PetrPudlák Zaktualizowano - ukończył dowód i dodał swoją opinię o [].
AndrewC,

@ PetrPudlák Czy uważasz, że powinniśmy dodać dowód, który []spełnia MonadPlusCatch? W tej chwili jest to tylko twierdzenie na HaskellWiki. >>= kjest zdefiniowany jawnie przy użyciufoldr ((++).k)
AndrewC

Przypuszczam, że masz na myśli MonadPlusDist , prawda? Myślę, że moglibyśmy, to uzupełniłoby dowód następstwa.
Petr Pudlák

@ PetrPudlák O tak, przepraszam. Zrobię
AndrewC,

6

Rzeczywiście to 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)
       )

Dane wyjściowe to

(Right Nothing, Left "something")

co oznacza, że MaybeT Eitherzawodzi lewe prawo dystrybucji Applicative.


Powód jest taki, że

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

ignoruje g(z powodu LeftCatch ) i ocenia tylko

return x `ap` a

ale różni się to od tego, co ocenia druga strona:

g `ap` a
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.