I was reading through the Hacklang docs on Collections, and came across this curious definition [paraphrased slightly]:

interface KeyedIterable<Tk, Tv> ...
interface ConstVector<+Tv> implements KeyedIterable<int, Tv>  ...

Of course, KeyedIterable must be read-only with respect to Tv, and indeed it is since its methods cannot modify its type. It could be specified to be covariant on at least Tv, but isn't.

I was wondering what impetus there could be to do this?

Edit: I read the definition wrong, KeyedIterable is actually defined as KeyedIterable<Tk, +Tv>, so this definition makes perfect sense. I'm just realizing now that it's not so much "should or should not", but rather "this is never possible".

  • 2
    To do what? Create an interface definition that, even though the designers could have specified to be covariant on tv, they didn't? Commented Apr 3, 2016 at 5:12
  • @RobertHarvey I think that's my confusion? I fail to see what the design incentive is to not make the parent class covariant on Tv, here or ever.
    – concat
    Commented Apr 3, 2016 at 5:30

2 Answers 2


No, an interface covariant on T should never implement an interface invariant on it. Covariance and invariance are different type variance concepts used in programming languages, particularly in relation to type hierarchies and polymorphism.

Covariance allows a more derived (or more specific) type to be used in place of a less derived (or less specific) type. In other words, it preserves the subtype relationship. For example, if we have an interface IFruit and a more specific interface IApple that extends IFruit, covariance would allow a function expecting an IFruit to accept an IApple as well.

  • Invariance include: The sort to be relegated and the sort appointed should be something very similar. This truly intends that there is no switch between a Youngster (More Inferred) type and a Parent (Less Determined) type. Covariance include: You can change from a Kid type to a Parent type. Commented Aug 17, 2023 at 10:02

Suppose interface KeyedIterable implements a method Combine that takes another KeyedIterable instance and merges it with itself. That would result in a mixed collection of different types. Then there may be a method GetTotal that adds all the values in the collection and returns the result. That could blow up, the plus may be overloaded for the subtype and be incompatible with the add of the base type.

This explanation appears to be appreciated: https://stackoverflow.com/questions/663254/why-doesnt-the-example-compile-aka-how-does-co-contra-and-in-variance-w/674090#674090

  • No, this is a bad example. He explicitly stated that KeyedIterable is read-only. This is just a bunch of hypotheticals that would basically just amount to "Because the interface design is shit", instead of any compelling reason.
    – DeadMG
    Commented Apr 3, 2016 at 10:21
  • Yes, I forgot about that part. Here's another thought. Isn't the KeyedIterable Tv implicitly covariant since it follows the ConstVector Tv? After all, there will be only one Tv at a time (per class declaration). You cannot have one value type for ConstVector and another for KeyedIterable. So a + or - with the second Tv would be meaningless. Commented Apr 3, 2016 at 15:51
  • Though in this particular case, another class ConstMap<+Tk, +Tv> implements KeyedIterable as well. My question actually comes from a specific use case: it's proven valuable to be able to return either Maps or Vectors, but annoyingly the invariance of Tk in KeyedIterable makes this impossible.
    – concat
    Commented Apr 3, 2016 at 16:25
  • I was wrong here too: I had assumed that ConstMap was covariant on Tk like the rest of the Const family (outside of ConstMapAccess and ConstIndexAccess which are consequently why ConstMap is invariant on Tk). I opened and subsequently closed a GitHub issue covering this.
    – concat
    Commented May 17, 2016 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.