英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论