I wonder if it is generally possible to unify the concepts of inheritance and parametric polymorphism ("generics"), especially regarding variance but also in terms how ("syntax") and where (use-site/declaration-site) they would have to be defined?
Consider this point of view:
S <: T
can be perceived as co-variant behavior, because input arguments accepting T
will also accept S
.final
modifier to a class definition), contra-variance is not possible as far as I have seen in most casesThere seems to be a non-negligible concept mismatch between both, considering
String[] <: Object[]
in Java/C#)In some languages it can be seen that both work together nicely though, like
class Foo extends Ordered[Foo]
to implement ordering/comparison behaviour.
By covariance/contravariance, one usually means this. Suppose X
, Y
, Z
are types. Suppose further that a → b
denotes a function type with an argument of type a
and a result of type b
. <:
denotes the subtype relation, or perhaps some other notion of "conformance". The ⇒ arrow reads "entails". Then the following holds:
X <: Y ⇒ (Z → X) <: (Z → Y)
X <: Y ⇒ (Y → Z) <: (X → Z)
That is, the function type constructor is covariant with respect to the result type (data source), and contravariant with respect to the argument type (data sink). This is a basic fact and you more or less cannot do anything too creative about it, like reversing the directions of arrows. Of course you can always use no-variance in place of co- or contravariance (most languages do).
Object types can be canonically encoded with function types, so there's not too much freedom here either. Every type parameter represents either data source (covariant) or data sink (contravariant) or both (novariant). If it's sound and contravariant in one language, then in another language it's going to be either contravariant or unsound.
I think Scala is pretty close to an ideal language in this respect. You cite an example that looks a lot like Scala, so you are most likely familiar with the language. I wonder why you think that its type system works nicely only in some instances. What are the other instances?
One theoretical work that every aspiring language designer should read is "A Theory of Objects" by Luca Cardelli.
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