Які відносини між Альтернативою, MonadPlus (LeftCatch) та MonadPlus (LeftDistributive)?


12

Слідування Що таке приклад Monad, який є Альтернативою, але не MonadPlus? :

Припустимо, - монада. Які відносини betweem будучи Alternative , а MonadPlusCatch і MonadPlusDistr ? мmmДля кожної з шести можливих пар я хотів би мати доказ того, що одна має на увазі інше, або зустрічний приклад того, що це не так.

(Я використовую

  • MonadPlusCatch відрізнити MonadPlus , яка задовольняє лівої Спіймати правило:

    mplus (return a) b = return a
    
  • MonadPlusDistr розрізняє MonadPlus, що задовольняє правило лівого розповсюдження :

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

див. MonadPlus на HaskellWiki .)


Мої сучасні знання + інтуїція:

  1. MonadPlusDist Альтернатива - швидше за все, правда - це здається простою, я вважаю, що я маю ескіз доказу, я перевірю це, і якщо це правильно, я опублікую його. AndrewC відповів на цю частину.
  2. Альтернатива MonadPlusDist - брехня - як показав AndrewC в своїй відповіді : це альтернатива , але відомо , що це не MonadPlusDist (це MonadPlusCatch ). 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

(Тому що , як Петро Pudlák зазначив, []контрприклад - це не задовольняє MonadPlusCatch але Задовольняє MonadPlusDist , отже , аплікативного )

Передбачається: закони 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)

<$>лема розширення
Припустимо, ми використовуємо стандартне походження функтора від монади, а саме (<$>) = 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 <$>вона не несе жодної ідіоматичної дії, вона чиста, тож можливо якось "переключити сторони".
Петро Пудлак

@ PetrPudlák Оновлено - закінчив доказ і додав свій слідство про [].
AndrewC

@ PetrPudlák Як ви думаєте, ми повинні додати доказ, який []задовольняє MonadPlusCatch? На даний момент це лише твердження про HaskellWiki. >>= kвизначено прямо з використаннямfoldr ((++).k)
AndrewC

Я думаю, ви маєте на увазі MonadPlusDist , чи не так? Я думаю, що ми могли б, це завершило б доказ наслідків.
Петро Пудлак

@ 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

ігнорує g(завдяки LeftCatch ) і оцінює просто до

return x `ap` a

але це відрізняється від того, що оцінює інша сторона:

g `ap` a
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.