此代码(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]]]
如何理解这条信息?
答案 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)))
如果Result
对T
有协变性(请注意所推断的所需类型),上述情况就不会发生:
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)