英文:
Match the context of MaybeT's Monad and Applicative: I actually found a counter-example
问题
I had a hard time finding out if MaybeT's Monad and Applicative have the same context. As you can see in the link above.
"same context" 的意思是
f <*> a = do
          x <- f
          y <- a
          return (x y)
我很难确定 MaybeT 的 Monad 和 Applicative 是否具有相同的上下文。正如您在上面的链接中所看到的。
"相同的上下文" 是指:
f <*> a = do
          x <- f
          y <- a
          return (x y)
I found a counter-example for MaybeT.
我找到了 MaybeT 的一个反例。
f = MaybeT [Nothing] :: MaybeT [] (Int -> Int)
a = MaybeT [Just 1, Just 2, Nothing] :: MaybeT [] Int
f <*> a = [Nothing, Nothing, Nothing]
do
  x <- f
  y <- a
  return (x y)
= [Nothing]
So, it seems like there's a discord in MaybeT's Applicative and Monad.
因此,看起来 MaybeT 的 Applicative 和 Monad 存在不一致。
How could we mix up >>, >, >>=, (<>) if there is a discord?
如果存在不一致,我们该如何混合使用 >>、>、>>=、(<>)?
I can't believe it. If there is such a discrepancy, shouldn't there be a bug in the many Haskell codes currently using MaybeT?
我难以相信。如果存在这样的不一致,那么目前使用 MaybeT 的许多 Haskell 代码中应该存在错误吗?
英文:
I had a hard time finding out if MaybeT's Monad and Applicative have the same context. As you can see in the link above.
The meaning of "same context" is
f <*> a = do
          x <- f
          y <- a
          return (x y)
I found a counter-example for MaybeT.
f = MaybeT [Nothing] :: MaybeT [] (Int -> Int)
a = MaybeT [Just 1, Just 2, Nothing] :: MaybeT [] Int
f <*> a = [Nothing, Nothing, Nothing]
do
x <- f
y <- a
return (x y)
= [Nothing]
So,
it seems like there's a discord in MaybeT's Applicative and Monad.
How could we mix up >> , > , >>= . (<>) if there is a discord?
I can't believe it.
If there is such a discrepancy, shouldn't there be a bug in the many Haskell codes currently using MaybeT?
答案1
得分: 4
以下是您要翻译的内容:
引述一条评论:
> MaybeT 的 (<*>) 与 Compose m Maybe 不同
确实:
ghci> import Data.Functor.Compose 
ghci> import Control.Monad.Trans.Maybe 
ghci> f = MaybeT [Nothing] :: MaybeT [] (Int -> Int)
ghci> a = MaybeT [Just 1, Just 2, Nothing] :: MaybeT [] Int
ghci> f <*> a
MaybeT [Nothing]
ghci> Compose (runMaybeT f) <*> Compose (runMaybeT a)
Compose [Nothing,Nothing,Nothing]
至于它们的区别,Compose 的 (<*>) 定义如下:
Compose u <*> Compose v = Compose (liftA2 (<*>) u v)
如果 被组合的两个应用函子也是单子(就像 [] 和 Maybe 一样),我们可以根据它们的单子实例来表达:
Compose (liftA2 (<*>) u v)
Compose $ do
    ui <- u  -- “i” 是“内部”的意思
    vi <- v
    return (ui <*> vi)
Compose $ do
    ui <- u
    vi <- v
    return $ do
        f <- ui
        a <- vi
        return (f a)
而对于内部函子是 Maybe 的情况,变成了:
Compose $ do
    ui <- u
    vi <- v
    return $ do
        f <- ui
        a <- vi
        Just (f a)
而 MaybeT 的 (<*>) 是:
mf <*> mx = MaybeT $ do
    mb_f <- runMaybeT mf
    case mb_f of
        Nothing -> return Nothing
        Just f  -> do
            mb_x <- runMaybeT mx
            case mb_x of
                Nothing -> return Nothing
                Just x  -> return (Just (f x))
让我们以接近上述样式的方式重新表述右边的内容:
MaybeT u <*> MaybeT v = MaybeT $ do
    ui <- u
    case ui of
        Nothing -> return Nothing
        Just f  -> do
            vi <- v
            case vi of
                Nothing -> return Nothing
                Just x  -> return (Just (f x))
Compose 的 (<*>) 在运行外部效果之前运行内部效果,因此在您的示例中,您得到了通常的列表 (<*>) 在外部级别运行,获得了一个由1 * 3 = 3个元素组成的列表。然而,MaybeT 的 (<*>) 运行其第一个参数(外部和内部的 Maybe)的效果,然后才转向第二个参数,仅在获得 Just 时才这样做,因此在您的示例中,f 中的 Nothing 仅产生另一个 Nothing,最终导致 [Nothing]。
英文:
Quoting a comment:
> MaybeT's (<*>) is different from Compose m Maybe
Indeed:
ghci> import Data.Functor.Compose 
ghci> import Control.Monad.Trans.Maybe 
ghci> f = MaybeT [Nothing] :: MaybeT [] (Int -> Int)
ghci> a = MaybeT [Just 1, Just 2, Nothing] :: MaybeT [] Int
ghci> f <*> a
MaybeT [Nothing]
ghci> Compose (runMaybeT f) <*> Compose (runMaybeT a)
Compose [Nothing,Nothing,Nothing]
As for how they differ, (<*>) for Compose is defined as:
Compose u <*> Compose v = Compose (liftA2 (<*>) u v)
If the two applicative functors being composed are also monads (as [] and Maybe are), we can express that in terms of their monad instances:
Compose (liftA2 (<*>) u v)
Compose $ do
    ui <- u  -- "i" is for "inner"
    vi <- v
    return (ui <*> vi)
Compose $ do
    ui <- u
    vi <- v
    return $ do
        f <- ui
        a <- vi
        return (f a)
Which, with the inner functor being Maybe, becomes:
Compose $ do
    ui <- u
    vi <- v
    return $ do
        f <- ui
        a <- vi
        Just (f a)
Whereas (<*>) for MaybeT is
mf <*> mx = MaybeT $ do
    mb_f <- runMaybeT mf
    case mb_f of
        Nothing -> return Nothing
        Just f  -> do
            mb_x <- runMaybeT mx
            case mb_x of
                Nothing -> return Nothing
                Just x  -> return (Just (f x))
Let's rephrase the right-hand side in a style closer to the one above:
MaybeT u <*> MaybeT v = MaybeT $ do
    ui <- u
    case ui of
        Nothing -> return Nothing
        Just f  -> do
            vi <- v
            case vi of
                Nothing -> return Nothing
                Just x  -> return (Just (f x))
(<*>) for Compose runs the outer effects before the inner ones, and so in your example you get the usual list (<*>) at the outer level, obtaining a list of 1 * 3 = 3 elements. (<*>) for MaybeT, however, runs the effects of its first argument (both the outer and the inner Maybe) before moving on to the second one, and that only if a Just is obtained, and so the Nothing lying in f in your example gives rise to merely another Nothing, resulting in [Nothing] overall.
答案2
得分: 2
As mentioned in the comments, the question has a false premise. The two expressions in the question,
f <*> a
and
do
  x <- f
  y <- a
  return (x y)
both produce the same result, MaybeT [Nothing].
You shouldn't be able to find examples in the wild where these two expressions differ for a single type. One of the laws listed in the Monad class is
m1 <*> m2 = m1 >>= (\x1 -> m2 >>= (\x2 -> return (x1 x2)))
which is just a desugaring of the identity you're trying to disprove. There are probably some examples out there of monads that break this law, but they're not "supposed" to.
英文:
As mentioned in the comments, the question has a false premise. The two expressions in the question,
f <*> a
and
do
  x <- f
  y <- a
  return (x y)
both produce the same result, MaybeT [Nothing].
You shouldn't be able to find examples in the wild where these two expressions differ for a single type. One of the laws listed in the Monad class is
m1 <*> m2 = m1 >>= (\x1 -> m2 >>= (\x2 -> return (x1 x2)))
which is just a desugaring of the identity you're trying to disprove. There are probably some examples out there of monads that break this law, but they're not "supposed" to.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论