In Scala, a Future is defined to be covariant whereas a Promise is invariant. It is said that a Promise can almost be made contravariant (https://issues.scala-lang.org/browse/SI-7467). Why is this the case?
If promise were covariant you would be able to do:
val p: Promise[Any] = Promise[String]()
p.success(1)
thereby completing a Promise[String] with an Int which would be unsafe.
A Promise is a mutable API, which does not fare well with covariance. Futures don't suffer this problem because you cannot manually complete them like you do with a Promise.
Let's say we have:
class Animal
class Cat extends Animal
class Dog extends Animal
If you want Promise[A] to be covariant over A, that means we want Promise[Cat] <: Promise[Animal] and Promise[Dog] <: Promise[Animal]. Let's suppose we can do this.
Okay, so let's say we have a Promise[Cat]:
val p: Promise[Cat] = ...
By our supposition, it's also a Promise[Animal]:
val q: Promise[Animal] = p
Promise has a method called complete which accepts a Try[T], which is also covariant. This means that a Try[Dog] is also a Try[Animal]. See where this is leading?
We'd be able to call:
val value: Try[Dog] = ...
q.complete(value)
Which would be legal, because we're trying to complete a Promise[Animal] with a Try[Animal], but oops, we also just tried to complete a Promise[Cat] with a Promise[Dog].
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