为什么这两个值都没有丢弃?

时间:2017-11-16 18:28:11

标签: haskell monads

ghci 中有以下内容:

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

Left 1.0 >> Right 1 >>= f

给出

Left 1.0

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

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

奇怪的是,该链接并未显示Either如何实现Monad类型类的方法。

3 个答案:

答案 0 :(得分:8)

  

据我所知[,] >>运算符丢弃第一个参数的monadic结果,

不,它确实。它或多或少看到LeftMaybe monad看到Nothing(主要区别在于Left也带有值)。因此,它有时用作“高级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的实施方式。

现在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的“更高级”版本,其中Left取代Nothing。因此,从某个时刻Left x开始,它就会保持Left x。无论我们如何约束它。

答案 1 :(得分:2)

请注意,该定义与您放弃序列运算符的左值相矛盾:

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

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

点击haddocks中Monad声明下的Either个实例,查看可以找到的source

答案 2 :(得分:2)

"结果"被丢弃的仅指a值包含在m a值中(而不是总是字面上),而不是其余值。如果是Either,则表示Right的值将被忽略,但不会被忽略LeftRight,还是Left的值{1}}。

如果您将>>= Either的定义与>>的默认定义结合起来,那么您会看到>>这里有效

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

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