I am a C++ / Java programmer and the main paradigm I happen to use in everyday programming is OOP. In some thread I read a comment that Type classes are more intuitive in na
Well, the short version is: Type classes are what Haskell uses for ad-hoc polymorphism.
...but that probably didn't clarify anything for you.
Polymorphism should be a familiar concept to people from an OOP background. The key point here, however, is the difference between parametric and ad-hoc polymorphism.
Parametric polymorphism means functions that operate on a structural type that itself is parameterized by other types, such as a list of values. Parametric polymorphism is pretty much the norm everywhere in Haskell; C# and Java call it "generics". Basically, a generic function does the same thing to a specific structure, no matter what the type parameters are.
Ad-hoc polymorphism, on the other hand, means a collection of distinct functions, doing different (but conceptually related) things depending on types. Unlike parametric polymorphism, ad-hoc polymorphic functions need to be specified individually for each possible type they can be used with. Ad-hoc polymorphism is thus a generalized term for a variety of features found in other languages, such as function overloading in C/C++ or class-based dispatch polymorphism in OOP.
A major selling point of Haskell's type classes over other forms of ad-hoc polymorphism is greater flexibility due to allowing polymorphism anywhere in the type signature. For instance, most languages won't distinguish overloaded functions based on return type; type classes can.
Interfaces as found in many OOP languages are somewhat similar to Haskell's type classes--you specify a group of function names/signatures that you want to treat in an ad-hoc polymorphic fashion, then explicitly describe how various types can be used with those functions. Haskell's type classes are used similarly, but with greater flexibility: you can write arbitrary type signatures for the type class functions, with the type variable used for instance selection appearing anywhere you like, not just as the type of an object that methods are being called on.
Some Haskell compilers--including the most popular, GHC--offer language extensions that make type classes even more powerful, such as multi-parameter type classes, which let you do ad-hoc polymorphic function dispatch based on multiple types (similar to what's called "multiple dispatch" in OOP).
To try to give you a bit of the flavor of it, here's some vaguely Java/C#-flavored pseudocode:
interface IApplicative<>
{
IApplicative Pure(T item);
IApplicative Map(Function mapFunc, IApplicative source);
IApplicative Apply(IApplicative> apFunc, IApplicative source);
}
interface IReducible<>
{
U Reduce(Function reduceFunc, U seed, IReducible source);
}
Note that we're, among other things, defining an interface over a generic type and defining a method where the interface type appears only as the return type, Pure
. Not apparent is that every use of the interface name should mean the same type (i.e., no mixing different types that implement the interface), but I wasn't sure how to express that.