看看Haskell的Either
Monad,有一个>>=
函数。
Prelude Map> let add100 = \x -> Right (x+100 :: Int)
Prelude Map> x
Right 5
Prelude Map> x >>= add100
Right 105
Prelude Map> let y = Left "..." :: Either String Int
Prelude Map> y >>= add100
Left "..."
但是,为什么Scala的Either[A,B]
有一个flatMap
,即等同于>>=
的功能?
scala> e
res5: Either[String,Int] = Right(1)
scala> e.
asInstanceOf fold isInstanceOf isLeft isRight
joinLeft joinRight left right swap
toString
此外,left
和right
的含义是什么?
scala> e.left
res6: scala.util.Either.LeftProjection[String,Int] = LeftProjection(Right(1))
scala> e.right
res7: scala.util.Either.RightProjection[String,Int] = RightProjection(Right(1))
答案 0 :(得分:5)
您可以使用需要两个功能的fold
,一个用于左侧,一个用于右侧,或使用right
投影视图:
val e: Either[String, Int] = Right(5)
def add100(i: Int): Either[String, Int] = Right(i + 100)
e.fold(identity, add100) // Right(105)
e.right.flatMap(add100) // Right(105)
因此,投影视图允许您将Either
实例视为将通过左或右类型映射的内容。 Either
scala-doc help file中解释了这一点。
答案 1 :(得分:3)
Either
不能拥有flatMap
,因为Either
不是monad。 Haskell通过支持两种类型中的一种而使其成为一个monad,但实际上没有理由这样做。 Either
表示“这可以是两种类型之一”。期。它不对这两种类型中的一种给予任何优惠待遇。
如果您使用Either
进行错误报告,那么您希望它偏向一侧,但这只是一个用户的一个用例,并将一个特殊用例硬编码到一般接口中糟糕的设计。对于该用例,您也可以使用Try
,这基本上是有偏见的Either
。
left
和right
会返回Either
的投影,其中 偏向一边。
然而,请注意Either
的设计和可用性经常被争论,并且它确实不是一个良好的API设计的光辉灯塔。这是Try
和ScalaZ \/
存在的原因之一。
答案 2 :(得分:1)
Scala的Either
类型是公正的。对于Try
,Future
等类型,map
和flatMap
对成功状态进行操作,但Either
不是这种情况(尽管{ {1}}通常有利于成功)。如果Right
没有真正的成功状态,那么Either
应该运行哪个值? flatMap
或Left
?这会让你有所投射。
Right
和left
是right
的预测,它们基本上是Either
的偏见版本。
Either
答案 3 :(得分:0)
Scala的
Either
类在Scala 2.12中进行了重新设计。在2.12之前,Either并没有偏见,也没有实现map和flatMap方法。正如书中的图像所示,Either在2.12中进行了重新设计以包括这些方法,因此如图所示,现在可以在Scala for-expression中使用它。
https://alvinalexander.com/photos/scala-either-left-right-2.12-biased-map-flatmap/
在Scala 2.12中,您可以例如这个:
for {
right1 <- either1
right2 <- either2
} yield (righ1 + right2)