为什么不丢弃 Either 值?

Why Either value is not discarded?

ghci 中有以下内容:

:m + Control.Monad.Error
let f x = Right x

Left 1.0 >> Right 1 >>= f

给予

Left 1.0

据我了解 >> 运算符丢弃第一个参数的单子结果, 但我看到它保存在这里。能解释一下吗?

http://hackage.haskell.org/package/base-4.10.0.0/docs/src/Data.Either.html#Either

奇怪的是,link 没有显示 Either 如何实现 Monad 类型类的方法。

As I understand[, the] >> operator discards monadic result of the first argument,

不,。它或多或少地看到 Left 就像 Maybe monad 看到 Nothing (主要区别在于 Left 也带有一个值)。因此,它有时被用作 "advanced Maybe",例如可以携带错误消息。

(>>) :: Monad m => m a -> m b -> m b 是一个函数,使得 f >> g 等价于 f >>= \_ -> gf >>= const g。这是 Monad 类型类中的默认实现。

因此,这取决于 (>>=) :: Monad m => m a -> (a -> m b) -> m b 的实施方式。

现在 Eitherimplemented as:

instance Monad (Either e) where
    Left  l >>= _ = Left l
    Right r >>= k = k r

所以这意味着如果左侧是 Left l,则忽略右侧 ,如果左侧是 Right r,然后 k 应用于 Right 构造函数包装的值。

因此我们可以将您的查询替换为(为清楚起见添加了括号):

   Left 1.0 >> Right 1 >>= f
=  (>>) (Left 1.0) (Right 1 >>= f)
-> Left 1.0

从语义上讲,您可以将 Either 视为 Maybe 的 "more advanced" 版本,其中 Left 取代了 Nothing。所以从 someting 是 Left x 的那一刻起,它就会保持 Left x。不管我们如何绑定它。

请注意该定义与您关于丢弃序列运算符的左值的信念相矛盾:

instance Monad (Either e) where
    Left  l >>= _ = Left l
    Right r >>= k = k r

事实上,在 Left 的情况下,Right 值被丢弃。

查看 source,单击黑线鳕中 Either 声明下的 Monad 实例即可找到。

被丢弃的 "result" 仅指 m a 值中包含的 a 值(并非总是字面意思),而不是其余部分。在 Either 的情况下,这意味着 Right 的值将被忽略,但无论是 Left 还是 RightLeft 的值都不会被忽略.

如果将 Either>>= 定义与 >> 的默认定义结合起来,您会发现这里的 >> 实际上是

Left  l >> x = Left  l >>= \_ -> x = Left l
Right r >> x = Right r >>= \_ -> x = x

并且第二个子句中的结果确实不依赖于 r