所以我正在使用Scala中的M
类型,并提出了有关Try
和Either
的以下内容:
def brokers(throw1: () => List[Int], throw2: List[Int] => List[String]) = {
println("brokers ===> " +
(Try(throw1())
.toEither
.filterOrElse(!_.isEmpty, Nil)
.flatMap(xs => Try(throw2(xs)).toEither) match {
case Right(s) => s
case Left(f) => throw f.asInstanceOf[Throwable]
})
)
}
一些测试运行:
brokers(() => List(1, 2, 3), (xs: List[Int]) => xs.map(_.toString))
brokers(() => Nil, (xs: List[Int]) => throw new RuntimeException("throw2"))
brokers(() => Nil, (xs: List[Int]) => xs.map(_.toString))
brokers(() => throw new RuntimeException("throw1"), (xs: List[Int]) => xs.map(_.toString))
brokers(() => List(1, 2, 3), (xs: List[Int]) => throw new RuntimeException("throw2"))
可是:
throw f
无法编译:“Serializable类型的表达式不符合预期类型Throwable”。因此演员。线程“main”中的异常 java.lang.ClassCastException:scala.collection.immutable.Nil $不能 被强制转换为java.lang.Throwable 练习$ .brokers(Practice.scala:57)at 实践$ $ .delayedEndpoint实践$ 1(Practice.scala:63)
为什么,Scala,为什么?
答案 0 :(得分:4)
回答我自己的问题,结果Either.filterOrElse
并不是我认为的那样。如果谓词不匹配,filterOrElse
实际上会将Either[A, B]
转换为Either[AA, B]
,其中AA
是提供给filterOrElse
的“零”元素。就我而言,它将Either[Throwable,List[Int]] = Right(List())
转换为Either[java.io.Serializable,List[Int]] = Left(List())
。因此编译错误,以及与case Left
和最终异常的匹配。 Serializable
必须来自逆变类型参数AA >: A
,因为猜测是什么,Throwable
和List
的第一个常见超类型是Serializable
。
我为此提交了SI-10044;会看到他们说的话。