Scala,神秘编译器错误:找到:结果[_>:需要选项[T]<:Option [Any]]的[String]:结果[Option [T]]

时间:2015-09-02 20:25:23

标签: scala

此代码(https://ideone.com/6y81ZT

object Main extends App {

    import scala.util.Try

    case class Result[T](value :T)

    def hi() = "hi"

    def safer[T](f : () => T) : Try[Result[Option[T]]] = {
        Try(hi)
            .map((r) => Result(Some(r)))
            .orElse(Try(Result(None)))
    }

    safer(hi)

}

产生编译错误:

Main.scala:12: error: type mismatch;  found   :
scala.util.Try[Main.Result[_ >: Some[String] with Option[T] <: Option[Any]]]
required: scala.util.Try[Main.Result[Option[T]]]

如何理解这条信息?

1 个答案:

答案 0 :(得分:3)

有几个问题。

首先,您将hi传递给Try.apply,这会导致其被固定为Try[String]而不是Try[T]

第二个错误来自Result(Some(r)),编译器期望Result[Option[T]]。 lambda中的类型过早地被固定到Result[Some[T]],这导致orElse推断出奇怪的复合类型。

Try(f())
    .map(r => Result(Option(r))) // Try[Result[Some[T]]]
    .orElse(Try(Result(None)))   // Try[Result[None]]

当(注意推断类型)时也会发生:

scala> Try(1).map(r => Result(Some(r))).orElse(Try(Result(None)))
res6: scala.util.Try[Result[_ >: Some[Int] with None.type <: Option[Int]]] = Success(Result(Some(1)))

如果ResultT有协变性(请注意所推断的所需类型),上述情况就不会发生:

case class Result[+T](value: T)

scala> Try(1).map(r => Result(Some(r))).orElse(Try(Result(None)))
res7: scala.util.Try[Result[Option[Int]]] = Success(Result(Some(1)))

不改变Result,这有效:

def safer[T](f: () => T) : Try[Result[Option[T]]] = {
    Try(f())
        .map(r => Result(Option(r)))
        .orElse(Try(Result(None)))
}

没有必要将外部Try保留在返回类型中,因为您永远不会真正返回失败。 (它始终由Result(None)恢复。

可以简化你所做的代码:

def safer[T](f: () => T) : Result[Option[T]] = Result(Try(f()).toOption)