Why can't a Promise be covariant
Asked Answered
W

2

7

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?

Wilhite answered 13/3, 2017 at 16:19 Comment(1)
There is a simple rule: if you can get a value out of it, then it is covariant (Try, Future, List, Vector, Option, ...). If you can put a value into it, then this is contravariant (Promise, Ordering, Consumer, ...).Bemean
S
8

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.

Stringboard answered 13/3, 2017 at 16:29 Comment(0)
C
3

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].

Cann answered 13/3, 2017 at 16:29 Comment(4)
Mutability is not a problem for variance here. I think Promise could be made contravariant.Bemean
@Bemean It it definitely a problem for covariance, which is what the question is asking.Cann
It's a problem for covariance, but not for varianceBemean
Thanks for the thorough answer. But I will accept @Lee's answer as it was posted 1m before yours and they're in essence the same :).Wilhite

© 2022 - 2024 — McMap. All rights reserved.