Haskell programmers tend to write code that can be reused in many ways. To achieve that, they avoid using specific types while writing code and use type variables instead. Depending on the types, the actual code may differ. This is possible thanks to type classes and their instances.
Type classes are usually considered Haskell’s most prominent feature. They originated in Haskell and were then taken up by other programming languages. A type class is defined with respect to some type variable. It contains a collection of methods, given by type signatures. We can define as many instances, or implementations, for specific types as we need.
Writing functions with respect to a type class, as opposed to using concrete types, allows you to be more general: a function will work with different types, even if they don’t exist at the time of declaring a type class. This makes type classes especially useful for libraries because we don’t know in advance which user-defined types will be used with our library in the future.