The differences in the two shape examples doesn't have to do with code inheritance - it has to do with subtype polymorphism. Existential types allow you to throw different subtypes into a collection and have the function dispatch on the common superclass type. The example without existential types demonstrates parametric polymorphism, but not subclass polymorphism. Generally speaking, OO programming is based on three properties (a) encapsulation; (b) inheritance; and (c) polymorphism. Well, Haskell has pretty good means of encapsulation (though I'm spoiled by ML at the moment). And existential types can get you subtype polymorphism. As far as inheritance, there's actually two kinds that occur in most OO languages. The first being type inheritance (which really just gets you subtype polymorphism). And then there's code inheritance - which is what you are trying to achieve. A language like Sather actually treats type inheritance and code inheritance as seperate things. Languages that mix the two concepts have their own set of difficulties, as the two forms of inheritance are sometimes at odds with each other. Anyhow, the classic case for code inheritance is from a re-use perspective - i.e. not having to repeat the code in multiple places. The classic problem with code inheritance is that it breaks encapsulation, as classes that reuse code from a superclass become tightly coupled with the implementation. At any rate, I consider inheritance to be a convenience mechanism, and not vitally necessary to the concepts of encapsulation, type inheritance, and polymorphism, though I realize that many do consider it important. From a Java perspective, you usually have to decide whether you want single inheritance via class extension, or multiple inheritance via interface implementation.
From the perspective of Java, the shape example that does not have code inheritance corresponds to the Java world of Interfaces - with Interfaces not allowing code inheritance.
Chris Rathman --- Cédric Paternotte <cpaternotte@gmail.com wrote:
1. Through existential types
As shown in the Shapes example at
http://www.angelfire.com/tx4/cus/shapes/haskell.html.
However, I couldn't spot the advantage over the standard version using normal classes at
http://www.angelfire.com/tx4/cus/shapes/haskell98.html
The getX function
still needs to be defined in both RectangleInstance
and CircleInstance. This is not what I call inheritance. Inheritance would make it possible to define getX only once in ShapeInstance. Or maybe the point was only to demonstrate polymorphism. But then what is the advantage of using existential types ? It just looks like more work compared to the standard version that also makes use of polymorphism. Or am I missing something ?