I have this definition:
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]
}
This won't compile with this error:
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
I don't get why. Can you, please, explain why this doesn't compile? Thanks
I will simplify the example a bit in order to make it easier to read.
Imagine you have trait
like this and let's assume that such declaration is legal:
trait Error[+E] {
def someMethod (f: String => Error[E]) // actually illegal
}
And implementations
class ErrorString extends Error[String] {
def someMethod (f: String => Error[String]) = {
val someVar: Error[String] = f("Somestring")
}
}
class ErrorInt extends Error[Int] {
...
}
As E
is covariant we can treat Error[String]
as subtype of Error[Any]
, so we can write the follwing
val anyError: Error[Any] = new ErrorString()
And then pass String => Error[Int]
function as a parameter to someMethod
val intErrorReturnFunction: String => Error[Any] = (k) => new ErrorInt
anyError.someMethod(intErrorReturnFunction) // actually illegal
But as anyError
is still have type Error[String]
in a background means that we are trying to pass String => Error[Int]
function to method with String => Error[String]
parameter.
So at the end we would have something like this
val someVar: Error[String] = f("Somestring"):Error[Int]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.