为什么不丢弃 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 >>= \_ -> g
和 f >>= const g
。这是 Monad
类型类中的默认实现。
因此,这取决于 (>>=) :: Monad m => m a -> (a -> m b) -> m b
的实施方式。
现在 Either
是 implemented 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
还是 Right
或 Left
的值都不会被忽略.
如果将 Either
的 >>=
定义与 >>
的默认定义结合起来,您会发现这里的 >>
实际上是
Left l >> x = Left l >>= \_ -> x = Left l
Right r >> x = Right r >>= \_ -> x = x
并且第二个子句中的结果确实不依赖于 r
。
在 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 >>= \_ -> g
和 f >>= const g
。这是 Monad
类型类中的默认实现。
因此,这取决于 (>>=) :: Monad m => m a -> (a -> m b) -> m b
的实施方式。
现在 Either
是 implemented 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
还是 Right
或 Left
的值都不会被忽略.
如果将 Either
的 >>=
定义与 >>
的默认定义结合起来,您会发现这里的 >>
实际上是
Left l >> x = Left l >>= \_ -> x = Left l
Right r >> x = Right r >>= \_ -> x = x
并且第二个子句中的结果确实不依赖于 r
。