views:

250

answers:

4

At first glance, there obvious distinctions between the two kinds of "class". However, I believe there are more similarities:

  • Both have different kinds of constructors.
  • Both define a group of operations that could be applied to a particular type of data, in other words, they both define an Interface.

I can see that "class" is much more concise in Haskell and it's also more efficient. But, I have a feeling that, theoretically, "class" and "abstract class" are identical.

What's your opinion?

+2  A: 

From: http://www.haskell.org/tutorial/classes.html

Before going on to further examples of the use of type classes, it is worth pointing out two other views of Haskell's type classes. The first is by analogy with object-oriented programming (OOP). In the following general statement about OOP, simply substituting type class for class, and type for object, yields a valid summary of Haskell's type class mechanism:

"Classes capture common sets of operations. A particular object may be an instance of a class, and will have a method corresponding to each operation. Classes may be arranged hierarchically, forming notions of superclasses and sub classes, and permitting inheritance of operations/methods. A default method may also be associated with an operation."

In contrast to OOP, it should be clear that types are not objects, and in particular there is no notion of an object's or type's internal mutable state. An advantage over some OOP languages is that methods in Haskell are completely type-safe: any attempt to apply a method to a value whose type is not in the required class will be detected at compile time instead of at runtime. In other words, methods are not "looked up" at runtime but are simply passed as higher-order functions.

Kirk Woll
+7  A: 

Er, not really, no.

For one thing, Haskell's type classes don't have constructors; data types do.

Also, a type class instance isn't really attached to the type it's defined for, it's more of a separate entity. You can import instances and data definitions separately, and usually it doesn't really make sense to think about "what class(es) does this piece of data belong to". Nor do functions in a type class have any special access to the data type an instance is defined for.

What a type class actually defines is a collection of identifiers that can be shared to do conceptually equivalent things (in some sense) to different data types, on an explicit per-type basis. This is why it's called ad-hoc polymorphism, in contrast to the standard parametric polymorphism that you get from regular type variables.

It's much, much closer to "overloaded functions" in some languages, where different functions are given the same name, and dispatch is done based on argument types (for some reason, other languages don't typically allow overloading based on return type, though this poses no problem for type classes).

camccann
I'd say they're pretty similar to interfaces in Java.
Ionuț G. Stan
@Ionuț G. Stan: Similar in spirit, certainly, and that's probably the least wrong comparison. There are enough differences in how they're used, though, that I don't encourage people to get too attached to the similarities except as a starting point.
camccann
I'll also add that a major difference 'in spirit' is that it is types, not objects/values, that are characterized by classes. Classes state facts about types, such as "Int is a Num", or "Maybe is a Functor". These are statements about the types, not about "objects" (eg, "hello" is not a Monoid, it's a String, but String is a Monoid).
mokus
The only difference that I see compared to Java is that when using type classes you don't have to alter the type definition in order to implement new type classes. In Java you have to alter the class definition in order to implement new interfaces. That's the only difference that I can spot right now.
Ionuț G. Stan
+4  A: 

Apart from the implementation differences, one major conceptual difference is regarding when the classes / type classes as declared.

If you create a new class, MyClass, in e.g. Java or C#, you need to specify all the interfaces it provides at the time you develop the class. Now, if you bundle your code up to a library, and provide it to a third party, they are limited by the interfaces you decided the class to have. If they want additional interfaces, they'd have to create a derived class, TheirDerivedClass. Unfortunately, your library might make copies or MyClass without knowledge of the derived class, and might return new instances through its interfaces thatt they'd then have to wrap. So, to really add new interfaces to the class, they'd have to add a whole new layer on top of your library. Not elegant, nor really practical either.

With type classes, you specify interfaces that a type provides separate from the type definition. If a third party library now contained YourType, I can just instantiate YourType to belong to the new interfaces (that you did not provide when you created the type) within my own code.

Thus, type classes allow the user of the type to be in control of what interfaces the type adheres to, while with 'normal' classes, the developer of the class is in control (and has to have the crystal ball needed to see all the possible things for what the user might want to use the class).

Sami
Other major differences: A type class isn't itself a type, so you can't mix different types with a common interface (without involving language extensions, at any rate); and type classes can be defined based on types anywhere in a function signature, not just the (implicit "this object") first argument as is typical with interfaces.
camccann
A: 

This slideshow may help you understand the similarities and differences between OO abstract classes and Haskell type classes: Classes, Jim, But Not As We Know Them.

missingfaktor