Consider this "legacy" code:
public interface IPersistentCollection {
IPersistentCollection cons(Object o);
}
Genericized in Java, it could become something like this:
public interface IPersistentCollection<T> {
IPersistentCollection<T> cons(T o);
}
Clearly adding a new item to a mutable Java collection shouldn't change the type of the existing collection. But unlike the Java collections, cons() returns a completely new, immutable collection, leaving the old collection unchanged, opening the possibility that it could meaningfully take on a different type than the original collection had.
Obviously, you should be able to cons an object of type Ford to a collection of Cars and get a collection of Cars back (covariance). I think this is covered by the above generic example.
If Car and Train both extended a Vehicle class, it would be handy to be able to cons a Train to a collection of Cars and get a collection of Vehicles back (contravariance). How would I even write that? I thought by declaring new bounded type variables, S and E for "Vehicle" and "Train" in this example:
// Illegal because of <S super T> <S super T, E extends S> IPersistentCollection<S> cons(E o); // Simpler, but still Illegal because java disallows <S super T> <S super T> IPersistentCollection<S> cons(S o);
If we want to assume that the programmer knows what they are doing, you should be allowed to cons something totally unrelated to a collection and get a collection of Objects back. I think this is the extreme case of contravariance, but I'm not sure there is even a name for it ("Dynamic Language" maybe?).
I think that if #2 were legal, it would cover cases #1 and #3.
My questions are:
A. To what degree is it possible to do #2 in Java?
B. Is #2 possible/easier in other languages? Scala? Haskell? ML?
C. In theory, a type system that preferred the most specific version of S in example 2 could handle a definition like this. What book can I read about type systems without a PHD in math? Is "Types and Programming Languages" by Pierce the best place to start?
Sample code would be appreciated. If I'm using terms like covariance and contravariance incorrectly, I would appreciate being politely corrected.
Object
.<T extends Vehicle & PurchasableItem>
, but Java is quite limited in how this can be used.