Some context, for those with no Haskell experience: a ‘typeclass’ (no relation to OOP ‘classes’) is a way of abstracting over a function which can be implemented for numerous different types, very much like ‘interfaces’ in Java or C#. For instance, the ‘Eq’ typeclass provides the equality operators:
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
Which can then be implemented for various types, allowing any of those types to be compared for equality using (==) and (/=). You can also write functions which are polymorphic over all types implementing a typeclass, e.g.:
allThreeUnequal :: Eq a => a -> a -> a
allThreeUnequal a b c = (a /= b) && (b /= c) && (a /= c)
-- (/=) here is provided by the ‘Eq a’ constraint
-- in the signature
I tend to think of typeclasses in Haskell — and especially the ones listed in the Typeclassopedia — almost as allowing the formalisation of design patterns and common conventions. For instance, many languages have multiple ‘map’ functions: one mapping a function over a list, one over a promise, and so on. Haskell, by contrast, unifies those in single ‘Functor’ typeclass, with one polymorphic function ‘fmap’. (The (in)famous ‘Monad’ typeclass is also very similar in its aims: compare C#, where precisely the same behaviour gets encoded in a mere convention declaring that a certain function should be named ‘SelectMany’.) The advantage of all this is that you can write very highly generic (hence reusable) code while still retaining typesafety. In fact, the effect tends to be remeniscient of duck typing, just more typesafe.
For people who know Rust, Haskell's type classes are like a more general version of Rust's traits. But that comparison suggests the wrong chronology; Haskell's type classes came a couple decades earlier.
I think functional programmers go too far in insisting how different functional programming is. A typeclass indeed is very similar to an interface in object oriented languages and you can even have default implementations of functions and you can subclass a typeclass (that is, inherit). Its used to solve many of the exact same kinds of problems that OOP classes are. They are fundamentally similar beasts.
> A typeclass indeed is very similar to an interface in object oriented languages
Agreed — as I mentioned in the post, typeclasses and interfaces are pretty similar. However, typeclasses and classes (i.e. the things used to make objects) are entirely different. I’ve seen numerous times when the similarity in names has caused immense confusion to people familiar with OOP, so I thought it would be worthwhile to clarify this.
(As for similarities between OOP and FP in general, you may be interested in this article: https://www.parsonsmatt.org/2018/03/22/three_layer_haskell_c.... I endorse their conclusion that typeclasses can be used to implement something which in principle is basically OOP. Also, starting from a different point of view, I will note that Smalltalk code tends to be pretty functional in its structure.)
They are different in important aspect - in OOP, conformance to an interface is defined where the class (new type) is defined, while conformance to a type class can be specified independently of type or type class definition.
This is really important for interoperability. With type classes, I can say that type (class in OOP) from library A conforms to a type class (interface in OOP) in library B (without A knowing anything about B), which is impossible to do with interfaces.
9 comments
[ 5.2 ms ] story [ 33.6 ms ] threadI think functional programmers go too far in insisting how different functional programming is. A typeclass indeed is very similar to an interface in object oriented languages and you can even have default implementations of functions and you can subclass a typeclass (that is, inherit). Its used to solve many of the exact same kinds of problems that OOP classes are. They are fundamentally similar beasts.
Agreed — as I mentioned in the post, typeclasses and interfaces are pretty similar. However, typeclasses and classes (i.e. the things used to make objects) are entirely different. I’ve seen numerous times when the similarity in names has caused immense confusion to people familiar with OOP, so I thought it would be worthwhile to clarify this.
(As for similarities between OOP and FP in general, you may be interested in this article: https://www.parsonsmatt.org/2018/03/22/three_layer_haskell_c.... I endorse their conclusion that typeclasses can be used to implement something which in principle is basically OOP. Also, starting from a different point of view, I will note that Smalltalk code tends to be pretty functional in its structure.)
This is really important for interoperability. With type classes, I can say that type (class in OOP) from library A conforms to a type class (interface in OOP) in library B (without A knowing anything about B), which is impossible to do with interfaces.
Does that involve adding code to make it conform?
Either way, there are languages based on classes and interfaces where you can do that.
And sure, we can discuss what OOP is, but I am using the most widely used definition of classes and interfaces, as understood by Java and .NET.