斯卡拉要么没有'flatMap`& Either.left / .right的含义

时间:2014-08-24 01:23:14

标签: scala haskell

看看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

此外,leftright的含义是什么?

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))

4 个答案:

答案 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中解释了这一点。


如果您熟悉Haskell,ScalaZ库可能适合您,它有自己的'或者'抽象称为\/(如here所述)。

答案 1 :(得分:3)

Either不能拥有flatMap,因为Either不是monad。 Haskell通过支持两种类型中的一种而使其成为一个monad,但实际上没有理由这样做。 Either表示“这可以是两种类型之一”。期。它不对这两种类型中的一种给予任何优惠待遇。

如果您使用Either进行错误报告,那么您希望它偏向一侧,但这只是一个用户的一个用例,并将一个特殊用例硬编码到一般接口中糟糕的设计。对于该用例,您也可以使用Try,这基本上是有偏见的Either

leftright会返回Either的投影,其中 偏向一边。

然而,请注意Either的设计和可用性经常被争论,并且它确实不是一个良好的API设计的光辉灯塔。这是Try和ScalaZ \/存在的原因之一。

答案 2 :(得分:1)

Scala的Either类型是公正的。对于TryFuture等类型,mapflatMap对成功状态进行操作,但Either不是这种情况(尽管{ {1}}通常有利于成功)。如果Right没有真正的成功状态,那么Either应该运行哪个值? flatMapLeft?这会让你有所投射。

Rightleftright的预测,它们基本上是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)