4 ms·
In short, the problem with covariant generics is that you can put a Banana in a Basket<Apple> (because a Basket<Apple> IS A Basket<Fruit>).
by pwpwp 15y ago
In short, the problem with covariant generics is that you can put a Banana in a Basket<Apple> (because a Basket<Apple> IS A Basket<Fruit>).
- someone13 15y agoSo, are there any languages that actually get this right? I'm sure Haskell does, being a strongly-typed, side-effect-free language. Are there any other languages that have this working properly?
- ecoffey 15y agoI believe that C# 4 gives you the ability to specify the co- or contra variance of a generic type.
- procrastitron 15y agoAs does Java, but they get it wrong for arrays. I don't know if C# has that problem or not.
- deleted 15y ago[deleted]
- snprbob86 15y agoC# copied Java's mistake in this respect. You can pass an Apple[] to something accepting a Fruit[] and get a runtime exception when you try to add a Banana to the Fruit[].
- Darmani 15y agoJava does; List<String> is not a subtype of List<Object>. This greatly confuses many programmers, since String[] is a subtype of Object[] (they made this mistake before Guy Steele got involved). Naturally, SML does as well. SML also has immutable lists, which are covariant.
- yummyfajitas 15y agoHaskell doesn't really have subtypes. Polymorphism in Haskell is typically implemented using typeclasses, which are closer to Java Interfaces than to subclasses.
- vilhelm_s 15y agoHaskell doesn't have any subtyping, so the problem doesn't come up. For languages that implement generics in a way that takes variance into account, you can look at e.g. Java (ignore the array class, but look at Vector<E>) or Scala. OCaml also has subtyping (for records and variants) and variance-annotated type variables (http://ocaml.janestreet.com/?q=node/99 http://ocaml.janestreet.com/?q=node/99).
- derleth 15y ago> Haskell doesn't have any subtyping Num looks like something that's been subtyped.
- nandemo 15y agoWell, it may look like but it isn't. Num is a typeclass, not a type. Like yummyfajitas said, typeclasses are similar to interfaces or abstract classes in Java, but they aren't the same. Consider Java's equals(). You can write 'a'.equals(foo) as long as foo is an Object. In contrast, look at Haskell's (==) function declared in Eq (I'm not giving an example using Num because Haskell provides some implicit conversions for numeric literals, which would introduce an unrelated complication in the example). (==) :: (Eq a) => a -> a -> Bool This functions accepts 2 arguments of any one type, as long that type is an instance of Eq. But we cannot use different types in the same call. That is, we can write ('a' == 'b') and ("foo" == "bar") but not ('a' = "foo"), because (==) is not defined for a Char and a String.