Scala.getOrElse方法之一

Scala.getOrElse方法之一,scala,either,Scala,Either,为什么我打字的时候一切都很好 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") 编译错误: 值getOrElse不是java.io.Serializable的成员 println(Right

为什么我打字的时候一切都很好

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")
编译错误:

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


因此我无法链接
getOrElse
方法调用对于
LeftProjection[a,B]
getOrElse
的签名是:

def getOrElse[AA >: A](or: ⇒ AA): AA
i、 e.它期望参数是某种类型的
AA
,它是
a
的超类型

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

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

但是,
String
LeftProjection[String,Int]
最具体的常见超类型是
Serializable


因此,如果你想链接
或者
s,你需要一种方法,它可以采用另一种
或者[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
  }
(您可以类似地编写
rightOrElse
,这是一个更常见的用例。)

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

implicit class EitherOps[A, B](e1: Either[A, B]) {
  def leftOrElse(e2: => Either[A, B]): Either[A,B] = // as above
}
因为这要求两个操作数都使用
或[A,B]
,而不是
A
B
(或其某些超类型),所以您可以将
s链接起来

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

这看起来是一种非常模糊的方法,可以获得相当直接的直通行为。为什么不干脆换一种方式写,而不是把你想要的行为强加给那些方法呢?