[Haskell-cafe] What I wish someone had told me...

Derek Elkins derek.a.elkins at gmail.com
Tue Oct 14 21:25:41 EDT 2008


On Wed, 2008-10-15 at 02:22 +0200, Daniel Fischer wrote:
> Am Mittwoch, 15. Oktober 2008 00:34 schrieb Derek Elkins:
> > It's not technically true.  Type classes and interfaces a la Java are
> > very fundamentally different neither is remotely capable of doing what
> > the other does.  
> 
> Could you elaborate on that, please?
> I always understood Java's interfaces to be somewhat similar to type classes 
> (and I learnt the bit of Java I know before I even knew the term "Functional 
> Programming", never really got the whole OO thing though).
> An interface, I thought, is a contract stating that the classes implementing 
> that interface provide certain operations (obeying some rules). If there's 
> more to interfaces, I'm happily unaware of that :)
> In what way is that "very fundamentally different" from type classes?

There are a lot of difference, for example, interfaces are "types"
insofar as you can have a variable of type IList; type classes are not
types, there are no variables of type Eq.  The fundamental one, however,
comes down to what it means to be "object-oriented."  One defining
property of object-oriented programming is dynamic dispatch.  This is
the fundamental difference between interfaces and type classes.

The instance selection for an interface is done at run-time and this is
inherently necessary.  The instance (in a different sense) selection for
type classes is almost always resolvable statically.  In Haskell 98
there is only one case that can't be done simply because doing so would
result in infinite code.  That case is polymorphic recursion.  With
extensions we get another case, namely existentials.  With existentials
we do get something like dynamic dispatch.  Nevertheless, the equation:
interfaces = type classes + existentials
does both interfaces and type classes a huge disservice, and at any rate
it's the existential not the type class that results in the properties
with which OO programmers are familiar.  Indeed,
interfaces = existentials + record of functions
is a better equation in some respects.

Anyways, the examples do the talking:

void draw(IEnumerable<IDrawable> drawables) {
    foreach(IDrawable drawable in drawables)
        drawable.Draw();
}

draw(new IDrawable[] { new Circle(), new Square(), new Star() });

The original motivating example of type classes is Eq.  Exactly the
problem that type classes were -literally- designed to solve is the
usual example of the "binary method problem" in the OO literature.  You
can see this problem in action in the messy semantics and brokenness and
gotchas surrounding the Equals method in C# and Java.  Then there are
examples that just inherently make no sense in a dynamic dispatch world:
Bounded, Read, the showList method of Show.

You can, if you want, -encode- various OO things into Haskell including
interfaces and even use type classes to do the lifting, but the result
is definitely an encoding and it is definitely not as simple as 
interfaces = type classes



More information about the Haskell-Cafe mailing list