我有这个定义:
sealed trait Error[+E, +A] {
final def map[B](f: A => B): Error[E, B] = {
this match {
case Ok(a) => Ok(f(a))
case Fail(e) => Fail(e)
}
}
final def flatMap[B](f: A => Error[E, B]): Error[E, B] = {
this match {
case Ok(a) => f(a)
case Fail(e) => Fail(e)
}
}
}
object Error {
final case class Ok[A](a: A) extends Error[Nothing, A]
final case class Fail[E](e: E) extends Error[E, Nothing]
}
此错误不会编译:
Error.scala:12: covariant type E occurs in contravariant position in type A => returnerror.Error[E,B] of value f
final def flatMap[B](f: A => Error[E, B]): Error[E, B] = {
^
one error found
我不明白为什么。您能否解释一下为什么不编译?谢谢
答案 0 :(得分:4)
我将简化示例以使其易于阅读。
假设您有trait
这样的代码,并假设这样的声明是合法的:
trait Error[+E] {
def someMethod (f: String => Error[E]) // actually illegal
}
和实现
class ErrorString extends Error[String] {
def someMethod (f: String => Error[String]) = {
val someVar: Error[String] = f("Somestring")
}
}
class ErrorInt extends Error[Int] {
...
}
由于E
是协变的,我们可以将Error[String]
视为Error[Any]
的子类型,因此我们可以写以下内容
val anyError: Error[Any] = new ErrorString()
然后将String => Error[Int]
函数作为参数传递给someMethod
val intErrorReturnFunction: String => Error[Any] = (k) => new ErrorInt
anyError.someMethod(intErrorReturnFunction) // actually illegal
但是由于anyError
在后台仍然具有类型Error[String]
,这意味着我们正试图将String => Error[Int]
函数传递给具有String => Error[String]
参数的方法。
所以最后我们会得到这样的东西
val someVar: Error[String] = f("Somestring"):Error[Int]