Why does this not compile?
trait Lol[A, SA] {
def flatMap[B, SB](f: A => Lol[B, SB]): Lol[B, SB] = ???
}
val p1: Lol[Int, String] = ???
val p2: Lol[Double, Nothing] = ???
val p5 = p1.flatMap(_ => p2)
Result:
found : Int => Lol[Double,Nothing]
required: Int => Lol[Double,SB]
val p5 = p1.flatMap(_ => p2)
^
Things start to compile when either:
flatMap
invocation are explicitSA
is covariant (wtf?)Nothing
is used in p2
(e.g. Null
)SB
does not occur in return type of flatMap
or occurs in covariant position of that return type (e.g. return type is Option[SB]
)The above workarounds are however not acceptable for me.
@retronym's commentary on SI-9453 explains the behaviour you're seeing. Here's a workaround of sorts ...
We can synthesize a type equivalent to Nothing
which won't cause the typer to retract the inference solution,
type ReallyNothing = Nothing { type T = Unit }
ie. Nothing
with a dummy refinement. Now with the example of the question,
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait Lol[A, SA] {
def flatMap[B, SB](f: A => Lol[B, SB]): Lol[B, SB] = ???
}
val p1: Lol[Int, String] = ???
val p2: Lol[Double, ReallyNothing] = ???
val p5 = p1.flatMap(_ => p2)
// Exiting paste mode, now interpreting.
scala.NotImplementedError: an implementation is missing
at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225)
... 37 elided
In order to better understand your problem, it can be simplified as:
class Lol[A]
def foo[B](f: Lol[B]) = f
foo(new Lol[Nothing])
which gives you the following compilation error:
error: type mismatch;
found : Lol[Nothing]
required: Lol[B]
Note: Nothing <: B, but class Lol is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
A possible solution is to update the snippet like that:
def foo[B <: Lol[_]](f: B) = f
Back to your original code:
trait Lol[A, SA] {
def flatMap[B <: Lol[_,_]](f: A => B): B = ???
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With