Apa hubungan antara Alternatif, MonadPlus (LeftCatch) dan MonadPlus (LeftDistributive)?

12

Tindak Lanjut Apa contoh dari Monad yang merupakan Alternatif tetapi bukan MonadPlus? :

Anggap adalah monad. Apa hubungan betweem m menjadi alternatif , sebuah MonadPlusCatch dan MonadPlusDistr ? mmUntuk masing-masing dari enam pasangan yang mungkin, saya ingin memiliki bukti bahwa satu menyiratkan yang lain, atau contoh tandingan yang tidak.

(Saya menggunakan

  • MonadPlusCatch untuk membedakan MonadPlus yang memenuhi aturan Left-Catch :

    mplus (return a) b = return a
    
  • MonadPlusDistr untuk membedakan MonadPlus yang mensahkan aturan Distribusi Kiri :

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

lihat MonadPlus di HaskellWiki .)


Pengetahuan + intuisi saya saat ini adalah:

  1. MonadPlusDist Alternatif - kemungkinan benar - sepertinya langsung, saya yakin saya punya sketsa bukti, saya akan memeriksanya dan jika itu benar, saya akan mempostingnya AndrewC menjawab bagian ini.
  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)
    

    lagi saya akan periksa dan posting. (Menariknya, hanya Maybeitu dapat dibuktikan, karena kita dapat menganalisis apakah aini Just somethingatau Nothing-. Lihat tersebut jawaban AndrewC ini)

  4. [][]
  5. []
  6. Maybe
Petr Pudlák
sumber

Jawaban:

8

(karena sebagai Petr Pudlák menunjukkan, []adalah counterexample - itu tidak memuaskan MonadPlusCatch tetapi tidak memuaskan MonadPlusDist , maka aplikatif )

Diasumsikan: Hukum MonadPlusDist

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

Untuk membuktikan: Hukum Alternatif

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

<*>ekspansi lemma
Anggaplah kita menggunakan derivasi standar dari aplikasi dari monad, yaitu (<*>) = apdan pure = return. Kemudian

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

karena

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)

<$>ekspansi lemma
Asumsikan kita menggunakan derivasi standar dari functor dari monad, yaitu (<$>) = liftM. Kemudian

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

karena

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 

Bukti

Asumsikan ( <+>, m0) memenuhi hukum MonadPlus. Sepele maka itu adalah monoid.

Dist. Kanan <*>

Saya akan buktikan

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

karena lebih mudah pada notasi.

(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

Identitas Kiri <*>

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

seperti yang dipersyaratkan.

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

seperti yang dipersyaratkan

AndrewC
sumber
1
Bagus. Saya bahkan curiga bahwa hukum kiri tersirat oleh hukum kanan untuk setiap Pemohon , tetapi sejauh ini saya tidak punya bukti. Intuisi adalah bahwa f <$>tidak melakukan tindakan idiomatik, itu murni, jadi mungkin saja entah bagaimana "beralih sisi".
Petr Pudlák
@ PetrPudlák Diperbarui - bukti jadi dan menambahkan bukti Anda tentang [].
AndrewC
@ PetrPudlák Apakah Anda pikir kami harus menambahkan bukti yang []memuaskan MonadPlusCatch? Saat ini hanya pernyataan di HaskellWiki. >>= kdidefinisikan secara eksplisit menggunakanfoldr ((++).k)
AndrewC
Saya kira maksud Anda MonadPlusDist , bukan? Saya pikir kita bisa, ini akan melengkapi bukti akibat wajarnya.
Petr Pudlák
@ PetrPudlák Oh ya saya minta maaf. Akan melakukan.
AndrewC
6

Contoh tandingan untuk MonadPlusCatch

Memang itu 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)
       )

Outputnya adalah

(Right Nothing, Left "something")

yang berarti itu MaybeT Either gagal hukum distribusi kiri Applicative.


Alasannya adalah itu

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

mengabaikan g(karena LeftCatch ) dan mengevaluasi hanya untuk

return x `ap` a

tetapi ini berbeda dari apa yang dinilai pihak lain untuk:

g `ap` a
Petr Pudlák
sumber