Haskell 什么&x2019;这是一个单子的例子,它是一个替代品,但不是单子?

Haskell 什么&x2019;这是一个单子的例子,它是一个替代品,但不是单子?,haskell,monads,applicative,alternative-functor,monadplus,Haskell,Monads,Applicative,Alternative Functor,Monadplus,在回答这个问题时,Edward Kmett说 此外,即使Applicative是Monad的一个超类,您最终还是需要MonadPlus类,因为遵守 empty <*> m = empty 因此,声称某物是一个MonadPlus比声称它是替代品更有力 很明显,任何非单子的应用函子都会自动成为非单子的备选方案的示例,但是Edward Kmett的回答意味着存在一个单子,它是一个替代,而不是MonadPlus:它的为空和将满足替代法则,1但不是单子plus法则。2我自己无法想出一个这样的

在回答这个问题时,Edward Kmett说

此外,即使
Applicative
Monad
的一个超类,您最终还是需要
MonadPlus
类,因为遵守

empty <*> m = empty
因此,声称某物是一个
MonadPlus
比声称它是
替代品
更有力

很明显,任何非单子的应用函子都会自动成为非单子的
备选方案的示例,但是Edward Kmett的回答意味着存在一个单子,它是一个
替代
,而不是
MonadPlus
:它的
为空
将满足
替代
法则,1但不是
单子plus
法则。2我自己无法想出一个这样的例子;有人知道吗


1我无法找到一组
替代
法则的规范参考,但我列出了我认为它们大概是问题的一半(搜索短语“正确分配”)。我认为应该遵守的四条法律是:

  • 右分配性(of
    ):
    (f g)a=(f a)(g a)
  • 右侧吸收(用于
    ):
    空a=empty
  • 左分布(of
    fmap
    ):
    f(ab)=(fa)(fb)
  • 左吸收(用于
    fmap
    ):
    f empty=empty
  • 我也很乐意接受一套更有用的
    替代法


    2我知道这一点;我对使用左分布或左捕捉的答案很满意,尽管我不太喜欢前者。

    你答案的线索在:

    什么规则?Martin和Gibbons选择幺半群、左零和左分布。这使得
    []
    成为一个MonadPlus,但不可能是
    或者
    IO

    因此,根据您喜欢的选择,
    可能不是MonadPlus(虽然有一个实例,但它不满足左分布)。让我们证明它满足备选方案

    可能是另一种选择
    
  • 右分配性(of
    ):
    (f g)a=(f a)(g a)
  • 案例1:
    f=Nothing

    (Nothing <|> g) <*> a =                    (g) <*> a  -- left identity <|>
                          = Nothing         <|> (g <*> a) -- left identity <|>
                          = (Nothing <*> a) <|> (g <*> a) -- left failure <*>
    
    (f <|> g) <*> Nothing = Nothing                             -- right failure <*>
                          = Nothing <|> Nothing                 -- left identity <|>
                          = (f <*> Nothing) <|> (g <*> Nothing) -- right failure <*>
    
    案例3:
    f=Just h,a=Just x

    (Just h <|> g) <*> Just x = Just h <*> Just x                      -- left bias <|>
                              = Just (h x)                             -- success <*>
                              = Just (h x) <|> (g <*> Just x)          -- left bias <|>
                              = (Just h <*> Just x) <|> (g <*> Just x) -- success <*>
    
    f <$> (Just x <|> b) = f <$> Just x                 -- left bias <|>
                         = Just (f x)                   -- success <$>
                         = Just (f x) <|> (f <$> b)     -- left bias <|>
                         = (f <$> Just x) <|> (f <$> b) -- success <$>
    
    案例2:
    a=x

    (Just h <|> g) <*> Just x = Just h <*> Just x                      -- left bias <|>
                              = Just (h x)                             -- success <*>
                              = Just (h x) <|> (g <*> Just x)          -- left bias <|>
                              = (Just h <*> Just x) <|> (g <*> Just x) -- success <*>
    
    f <$> (Just x <|> b) = f <$> Just x                 -- left bias <|>
                         = Just (f x)                   -- success <$>
                         = Just (f x) <|> (f <$> b)     -- left bias <|>
                         = (f <$> Just x) <|> (f <$> b) -- success <$>
    
    也许
    不是MonadPlus 让我们来证明
    可能不是MonadPlus的断言:我们需要证明
    mplus a b>>=k=mplus(a>=k)(b>=k)
    并不总是成立的。诀窍是,像以往一样,使用一些绑定来隐藏非常不同的值:

    a = Just False
    b = Just True
    
    k True = Just "Made it!"
    k False = Nothing
    
    现在

    在这里,我使用bind
    (>>=)
    从胜利的嘴中攫取失败(
    什么都没有
    ),因为
    一个假
    看起来像是成功

    mplus (Just False >>= k) (Just True >>= k) = mplus (k False) (k True)
                                               = mplus Nothing (Just "Made it!")
                                               = Just "Made it!"
    
    这里的失败(
    k False
    )是提前计算出来的,所以被忽略了,我们
    “成功了!”

    所以,
    mplus a b>=k=Nothing
    但是
    mplus(a>=k)(b>=k)=只是“成功了!”

    您可以像我一样使用
    >=
    来打破
    mplus
    对于
    可能
    的左偏

    本人证明的有效性: 以防你觉得我没有做足够繁琐的推导,我会证明我使用的身份:

    首先

    Nothing <|> c = c      -- left identity <|>
    Just d <|> c = Just d  -- left bias <|>
    
    第三,其他三个需要更多的工作:

    Nothing <*> c = Nothing        -- left failure <*>
    c <*> Nothing = Nothing        -- right failure <*>
    Just f <*> Just x = Just (f x) -- success <*>
    
    Nothing c=Nothing——左侧故障
    c Nothing=Nothing--正确的失败
    Just f Just x=Just(f x)--成功
    
    这来自于定义

    instance Applicative Maybe where
        pure = return
        (<*>) = ap
    
    ap :: (Monad m) => m (a -> b) -> m a -> m b
    ap =  liftM2 id
    
    liftM2  :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
    liftM2 f m1 m2          = do { x1 <- m1; x2 <- m2; return (f x1 x2) }
    
    instance  Monad Maybe  where
        (Just x) >>= k      = k x
        Nothing  >>= _      = Nothing
        return              = Just
    
    实例应用程序可能在哪里
    纯=返回
    ()=ap
    ap::(单子m)=>m(a->b)->m a->m b
    ap=liftM2 id
    liftM2::(单子m)=>(a1->a2->r)->M1->M2->MR
    liftM2 f m1 m2=do{x1=k=kx
    无>>==无
    返回=刚刚
    
    所以

    mf mx=ap mf mx
    =liftM2 id mf mx
    =do{f
    仅(f x)
    

    因此,如果
    mf
    mx
    为零,则结果也是
    Nothing
    ,而如果
    mf=Just f
    mx=Just x
    ,则结果是
    Just(f x)

    我一直认为替代法和MonadPlus的唯一法则是幺半群法则。或者,更具体地说,我认为应该有只包含幺半群法则的类型类,任何额外的法则都应该分配给子类。@GabrielGonzalez在实践中,这种事情无论如何都会发生。在我的回答中我证明了基地的一个MonadPlus的例子不符合这些定律。AndrewC:当然应该这么说。人们总是这么说。我们一直在与东亚作战。(谢谢,我回去也确定了我对另一个问题的答案。)哦,我刚刚意识到(读了@PetrPudlák的评论)-我认为我们应该增加关联性,特别是,(ab)c=a(bc)。@AndrewC:我认为这些是附加的非幺半群定律,因为文档中唯一说的是,
    Alternative
    在原始上下文中是明确的,但你是对的,我可能应该更明确一些。(我也可以很容易地制作出一个版本的
    也许
    ,带有右偏,既不满足左捕捉也不满足左分布,所以从任何定义来看都不会是MonadPlus,但它会满足另一种选择。)我想知道,从某种意义上来说,是否有可能证明任何东西都是
    MonadPlus
    (幺半群、左零和左分布)或另一个(幺半群、左零和左捕获)已经是
    的备选方案了
    ?这将为原始问题提供一个非常笼统的答案。@PetrPudlák我已经研究过了,你的问题(我相信)有一个有趣的答案。你想把它作为一个问题问吗?
    Nothing <|> c = c      -- left identity <|>
    Just d <|> c = Just d  -- left bias <|>
    
    instance Alternative Maybe where
        empty = Nothing
        Nothing <|> r = r
        l       <|> _ = l
    
    f <$> Nothing = Nothing    -- failure <$>
    f <$> Just x = Just (f x)  -- success <$>
    
    instance  Functor Maybe  where
        fmap _ Nothing       = Nothing
        fmap f (Just a)      = Just (f a)
    
    Nothing <*> c = Nothing        -- left failure <*>
    c <*> Nothing = Nothing        -- right failure <*>
    Just f <*> Just x = Just (f x) -- success <*>
    
    instance Applicative Maybe where
        pure = return
        (<*>) = ap
    
    ap :: (Monad m) => m (a -> b) -> m a -> m b
    ap =  liftM2 id
    
    liftM2  :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
    liftM2 f m1 m2          = do { x1 <- m1; x2 <- m2; return (f x1 x2) }
    
    instance  Monad Maybe  where
        (Just x) >>= k      = k x
        Nothing  >>= _      = Nothing
        return              = Just
    
    mf <*> mx = ap mf mx
              = liftM2 id mf mx
              = do { f <- mf; x <- mx; return (id f x) }
              = do { f <- mf; x <- mx; return (f x) }
              = do { f <- mf; x <- mx; Just (f x) }
              = mf >>= \f ->
                mx >>= \x ->
                Just (f x)