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. Future
s 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]
.
Promise
could be made contravariant. –
Bemean © 2022 - 2024 — McMap. All rights reserved.