Alternative、MonadPlus(LeftCatch)とMonadPlus(LeftDistributive)の関係は何ですか?


12

フォローアップモナドプラスではなく、代替であるモナドの例は何ですか?

がモナドであると仮定します。関係はbetweem何ですかmがあることオルタナティブMonadPlusCatchMonadPlusDistrmm6つの可能性のあるペアのそれぞれについて、一方が他方を暗示しているという証拠、またはそれが暗示していない反例のいずれかを持ちたいと思います。

(私は使用しています

  • 左キャッチ規則を満たすMonadPlusを区別するMonadPlusCatch

    mplus (return a) b = return a
    
  • 左分配規則を満足させる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証明できるのaJust something、そうであるかどうかを分析できるからですNothing-前述のAndrewCの答えを参照してください。)

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

回答:


8

(ペトルスキー-パドラックが指摘したようので、[]反例である-それは満たさないMonadPlusCatchなく満たしていMonadPlusDist、したがってApplicativeのを

想定:MonadPlusDist Laws

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

<*>拡張補題
モナドからの標準的な派生、つまり(<*>) = apand を使用すると仮定します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
すごい。Applicativeの左の法則は右の法則によって暗示されているのではないかと疑っていますが、今のところ証拠はありません。直観は、f <$>慣用的なアクションを何も運んでいないということです。それは純粋なので、どうにか「側面を切り替える」ことが可能かもしれません。
ペトルプドラク

@PetrPudlák更新済みの証明を更新し、についての推論を追加しました[]
-AndrewC

@PetrPudlákMonadPlusCatchを[]満たす証明を追加すべきだと思いますか?現時点では、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

gLeftCatchによる)を無視し、次のように評価します

return x `ap` a

しかし、これは反対側が評価するものとは異なります:

g `ap` a
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.