Scala.E或getOrElse方法

MyT*_*tle 7 scala either

为什么当我打字时一切正常?

Right(2).left getOrElse Right(4).left getOrElse Left("Error")
Run Code Online (Sandbox Code Playgroud)

但是当我键入此编译失败?

Right[String, Int](2).left getOrElse Right[String, Int](4).left getOrElse Left[String, Int]("Error")
Run Code Online (Sandbox Code Playgroud)

编译错误:

value getOrElse不是java.io.Serializable
println 的成员(RightString,Int.left getOrElse RightString,Int.left getOrElse LeftString,Int)

所以我不能连接getOrElse方法调用

Ben*_*mes 8

签名getOrElseLeftProjection[A, B]是:

def getOrElse[AA >: A](or: ? AA): AA
Run Code Online (Sandbox Code Playgroud)

即它期望参数是某种类型AA的超类型A.

在第一个例子,你离开了类型标注,让编译器来推断NothingA.然后,您提供了一个类型的参数LeftProjection[Nothing, Int].

因为Nothing所有类型的子类型,所以LeftProjection[Nothing, Int]通常是超类型!类型系统中的这种特殊情况意味着它几乎是偶然地进行了类型检查.

然而,最具体的共同父类型StringLeftProjection[String, Int]Serializable.


所以,如果你想链接Eithers,你需要一个可以接受另一个的方法Either[A, B],而不仅仅是一个A或者B.

您似乎想要的方法如下所示:

def leftOrElse[A, B](e1: Either[A, B], e2: => Either[A, B]): Either[A,B] =
  e1 match {
    case Left(a) => Left(a)
    case Right(b) => e2
  }
Run Code Online (Sandbox Code Playgroud)

(您可以类似地编写rightOrElse,这是一个更常见的用例.)

如果你使用implicits将它作为扩展方法,这在语法上会变得更有用.

implicit class EitherOps[A, B](e1: Either[A, B]) {
  def leftOrElse(e2: => Either[A, B]): Either[A,B] = // as above
}
Run Code Online (Sandbox Code Playgroud)

因为这需要Either[A, B]两个操作数,而不是AB(或其某些超类型),你可以链接你的Eithers.

scala> Right[String, Int](2) leftOrElse Right[String, Int](4) leftOrElse Left[String, Int]("Error")
res1: Either[String,Int] = Left(Error)
Run Code Online (Sandbox Code Playgroud)