Scala 协变类型E出现在类型A=>returnerror的逆变位置。值f的错误[E,B]

Scala 协变类型E出现在类型A=>returnerror的逆变位置。值f的错误[E,B],scala,Scala,我有这样的定义: 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] = { th

我有这样的定义:

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

我不明白为什么。你能解释一下为什么这个不能编译吗?谢谢

为了便于阅读,我将简化这个示例

假设你有这样的特点,让我们假设这样的声明是合法的:

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

但由于anyError仍然是,所以在后台仍有类型Error[String],这意味着我们试图将String=>Error[Int]函数传递给带有String=>Error[String]参数的方法

所以最后我们会有这样的东西

 val someVar: Error[String] = f("Somestring"):Error[Int]

我将简化这个例子,使它更容易阅读

假设你有这样的特点,让我们假设这样的声明是合法的:

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

但由于anyError仍然是,所以在后台仍有类型Error[String],这意味着我们试图将String=>Error[Int]函数传递给带有String=>Error[String]参数的方法

所以最后我们会有这样的东西

 val someVar: Error[String] = f("Somestring"):Error[Int]
错误[String]作为错误[Any]的超类型。我想你指的是子类型而不是超类型,或者将错误的顺序交换为错误的超类型[Any]。我想你指的是子类型而不是超类型,或者交换错误的顺序。