7

为什么当我输入这一切都很好?

Right(2).left getOrElse Right(4).left getOrElse Left("Error")

但是当我输入这个编译失败?

Right[String, Int](2).left getOrElse Right[String, Int](4).left getOrElse Left[String, Int]("Error")

编译错误:

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

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

4

1 回答 1

8

getOrElsefor a的签名LeftProjection[A, B]是:

def getOrElse[AA >: A](or: ⇒ AA): AA

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

在第一个示例中,您省略了类型注释,允许编译器推断Nothing. A然后,您提供了一个类型为 的参数LeftProjection[Nothing, Int]

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

String然而, and最具体的常见超类型LeftProjection[String, Int]Serializable


所以,如果你想链接Eithers,你需要一个可以接受另一个的方法Either[A, B],而不仅仅是一个Aor 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
  }

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

如果您使用隐式将其作为扩展方法,这在语法上会变得更有用。

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

因为这需要Either[A, B]两个操作数,而不是Aor B(或其某些超类型),所以您可以链接您Either的 s。

scala> Right[String, Int](2) leftOrElse Right[String, Int](4) leftOrElse Left[String, Int]("Error")
res1: Either[String,Int] = Left(Error)
于 2013-08-21T20:31:35.447 回答