3 ms·
It also happens with method overloading. In Java, you can't have a class that has both of these methods at the same time: Integer sum(List<Integer> values)
by bunderbunder 8y ago
It also happens with method overloading. In Java, you can't have a class that has both of these methods at the same time:
Integer sum(List<Integer> values) { ... }
float sum(List<Float> values) { ... }
because, as far as Java is concerned, both of these methods have exactly the same argument list.
You also have no way in the language to express things like "Map<String, Option<Integer>>.class", which has some ergonomic implementations. (e.g., see: http://gafter.blogspot.com/2006/12/super-type-tokens.html http://gafter.blogspot.com/2006/12/super-type-tokens.html)
The gotcha here, though, is that Haskell doesn't have these problems, or the one with implementing multiple specializations of the same generic type, even though it erases types much more completely than Java does.
I'm not much of an expert on language design, but that leaves me thinking that there's probably a lot of stuff we lay at the feet of Java's type erasure that is actually more properly attributable to having a type system that is broken in some fundamental way.
Or maybe it's the way that type erasure interacts with dynamic dispatch in an object-oriented language? Since the dynamic dispatch means that there are decisions about datatypes that a language like Haskell or ML can sort out at compile time, but that an OO language like Java must delay until run-time?
- int_19h 8y agoIn this case I suspect Haskell just passes the appropriate "view" of the value, since it knows what the target type class is at any given point, and - most importantly - it can't be "downcast" later through that same value; you can't do a runtime check for whether a given Convertible<T> is also Convertible<U> (either explicitly, or observable via dynamic dispatch). In Java, it's possible, so even if the code never actually does that anywhere, it always has to be pessimistic and assume that someone somewhere might. But I'm not sure that truly counts as type erasure. If that's how things are done, then the type class of every such value is effectively encoded by the set of function values that are passed around, and could be queried at runtime - the Java equivalent would be to tag every reference with its class, including all generic parameters used to instantiate it.