Scala尝试和奇怪的行为

时间:2016-11-11 10:34:35

标签: scala monads either

所以我正在使用Scala中的M类型,并提出了有关TryEither的以下内容:

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

可是:

  1. throw f无法编译:“Serializable类型的表达式不符合预期类型Throwable”。因此演员。
  2. 样本运行2的例外:
  3.   

    线程“main”中的异常   java.lang.ClassCastException:scala.collection.immutable.Nil $不能   被强制转换为java.lang.Throwable   练习$ .brokers(Practice.scala:57)at   实践$ $ .delayedEndpoint实践$ 1(Practice.scala:63)

    为什么,Scala,为什么?

1 个答案:

答案 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,因为猜测是什么,ThrowableList的第一个常见超类型是Serializable

我为此提交了SI-10044;会看到他们说的话。