Most software developers are familiar with the OOP motto “everything is an object.” People accustomed to C++ classes often find the Haskell concept of type classes difficult to grasp. Why is it so different?

C++ classes pack functions together with data, which makes it convenient to represent and consume data. Use of interfaces (abstract classes) allow classes to interact by contract, instead of directly manipulating the data in the other class. There exist alternative ways in C++ to accomplish such functionality (function pointers, discriminated unions), yet these techniques are not as handy as classes. Classes are also the primary way to hiding implementation details. Moreover, classes represent a handy way to group related functionality together. It’s extremely useful to browse the structure of large C++ project in terms of classes instead of individual functions.

Haskell provides other solutions for these problems.

1.1 Type with several representations: use algebraic data type (ADT)
For the types with different representations, algebraic data types (ADT) – an analog of discriminated unions – are supported:

The equivalent C++ implementation using inheritance requires much more machinery than our 5 line, ADT-based solution. This also illustrates a Haskell benefit–it’s much easier to define types/functions. Perhaps objects are not as great as you thought before. :D