正如Alexey所指出的,你应该指定Result的map的返回类型(否则Failure类型是不明确的,虽然你可以指定Failure类型而不是Failure[B]):
sealed trait Result[A]{
// specify the return type Result[B]
def map[B](f: A => B): Result[B] = this match{
case Success((a, rest)) => Success((f(a), rest))
case Failure(m) => Failure(m) // alternatively use Failure[B](m) here
}
}
case class Success[A](result: (A, List[Char])) extends Result[A]
case class Failure[A](message: String) extends Result[A]
object Utils{
def map[A,B](r: Result[A], f: A => B):Result[B] = {
r.map(f)
}
}
这将为失败提供正确的类型:
scala> val f = Failure[Int]("oops")
Failure("oops"): Failure[Int]
scala> Utils.map(f, {i: Int => 4})
Failure("oops"): Result[Int]
vs(使用下面的协变解决方案):
scala> Utils.map(f, {i: Int => 4})
Failure(oops): Product with Serializable with Result[_37] forSome { type _37 <: Int }
这不是你想要的!
最初我建议你让你的类型协变(+A):
sealed trait Result[+A]{
def map[B](f: A => B) = this match{
case Success((a, rest)) => Success((f(a), rest))
case Failure(m) => Failure(m)
}
}
case class Success[A](result: (A, List[Char])) extends Result[A]
case class Failure[A](message: String) extends Result[A]
object Utils{
def map[A,B](r: Result[A], f: A => B):Result[B] = {
r.map(f)
}
}
更多讨论请见this great blogpost。
引用部分帖子:
子类型关系
假设 Orange 类扩展 Fruit 成立。
如果声明了Box[A] 类,那么A 可以以+ 或- 为前缀。
没有注解的A是不变的,即:
Box[Orange]与Box[Fruit]没有继承关系。
+A 是协变的,即:
Box[Orange] 是 Box[Fruit] 的子类型。
var f: Box[Fruit] = new Box[Orange]() 是允许的。
-A 是逆变的,即:
Box[Fruit] 是Box[Orange] 的子类型。
var f: Box[Orange] = new Box[Fruit]() 是允许的。