Type classes
Tags: functional, haskell
Published: 2019-03-26 22:30:14

---
title: Type classes
description: #100DaysOfFP Day 14: Review of Haskell book's 6th chapter
cover_image: https://images.pexels.com/photos/905847/pexels-photo-905847.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260
series: 100 Days Of FP
tags: fp,haskell
published: true
---

Here we go with another chapter of the [Haskell book](http://haskellbook.com/) from [Delft Haskell Study Group Session #4](https://www.meetup.com/Delft-Haskell-Study-Group/events/259694156/). This time it was chapter 6, about Type classes.

As always, quotes are from the book and meant as a recap.

## Type classes?

> Type classes and types in Haskell are, in a sense, opposites. Where a declaration of a type defines how that type in particular is created, a declaration of a type class defines how a set of types are _consumed_ or used in computations.
>
> Type classes allow us to generalize over a set of types in order to define and execute a standard set of features for those types.

Type classes are sort of _interfaces_ than can work on several types. Through type classes Haskell achieves constrained or _ad-hoc_ polymorphism.

> The goal is to define a datatype by cases, where one can add new cases to the datatype and new functions over the datatype, without recompiling existing code, and while retaining static type safety (e.g., no casts). [^1]

So we have type classes as constraints or rules and we say a type implements or instantiates the type classes by, well, implementing or instantiating those constraints/rules.

This is, for example, what the `Bool` type implements.

```
λ> :i Bool
data Bool = False | True        -- Defined in ‘GHC.Types’
instance Eq Bool -- Defined in ‘GHC.Classes’
instance Ord Bool -- Defined in ‘GHC.Classes’
instance Show Bool -- Defined in ‘GHC.Show’
instance Read Bool -- Defined in ‘GHC.Read’
instance Enum Bool -- Defined in ‘GHC.Enum’
instance Bounded Bool -- Defined in ‘GHC.Enum’
```

That means that all the constraints defined for `Eq`, `Ord`, `Show`, `Read`, `Enum` and `Bounded` are available to be used with `Bool`s.

Let's take a look at `Ord`

```
λ> :i Ord
class Eq a => Ord a where
  compare :: a -> a -> Ordering
  (<) :: a -> a -> Bool
  (<=) :: a -> a -> Bool
  (>) :: a -> a -> Bool
  (>=) :: a -> a -> Bool
  max :: a -> a -> a
  min :: a -> a -> a
  {-# MINIMAL compare | (<=) #-}
-- ...
```

We can see it defines all ordering related operations, and also a minimal set of operations that need to be defined in order to instantiate the type class.

It's also constrained by `Eq`, the type class for equality. Which makes sense, how can we order things if without knowing when they are equal or not.

```
λ> :i Eq
class Eq a where
  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool
  {-# MINIMAL (==) | (/=) #-}
-- ...
```

By this definition we can see the constraints. All the `a`s aren't fully polymorphic, they are constrained by the type class (`Eq` or `Ord`).

```
λ> :t (==)
(==) :: Eq a => a -> a -> Bool
```

Which can be any of the types that implement the type class.

Once we apply an argument it becomes more concrete:

```
λ> :t (==) 1
(==) 1 :: (Eq a, Num a) => a -> Bool
Prelude
λ> :t (==) (1 :: Int)
(==) (1 :: Int) :: Int -> Bool
```

## Writing type classes

```haskell
data DayOfWeek
  = Mon
  | Tue
  | Wed
  | Thu
  | Fri
  | Sat
  | Sun

data Date =
  Date DayOfWeek Int

instance Eq DayOfWeek where
  (==) Mon Mon = True
  (==) Tue Tue = True
  (==) Wed Wed = True
  (==) Thu Thu = True
  (==) Fri Fri = True
  (==) Sat Sat = True
  (==) Sun Sun = True
  (==) _ _ = False

instance Eq Date where
  (==) (Date weekday dayOfMonth)
       (Date weekday' dayOfMonth') =
    weekday == weekday' && dayOfMonth == dayOfMonth'
```

Implementing type classes is quite straightforward, we have to define the required functions (the rules) for our type and that's it.

When writing instances of types with polymorphic parameters (like `Date` from the example) we need to make sure those parameters also are constrained.

The following would result in a compile error.

```haskell
data Identity a =
  Identity a

instance Eq (Identity a) where
  (==) (Identity v) (Identity v') = v == v'
```

It does not work because `a` is fully polymorphic (i.e. not constrained), but in order to compare it it needs to implement `Eq`.

```haskell
instance Eq a => Eq (Identity a) where
  (==) (Identity v) (Identity v') = v == v'
```

Making `a` constrained by `Eq` solves the problem :muscle:

We could also add `Ord` as a constraint, since it also requires `Eq`:

```haskell
instance Ord a => Eq (Identity a) where
  (==) (Identity v) (Identity v') = v == v'
```

Although that would work, it is not good to require more than is needed. Since we are not using any `Ord` functions we are better off with `Eq`.

For some type classes we do not need to write them ourselves, the compiler is smart enough to derive them.

```haskell
data DayOfWeek
  = Mon
  | Tue
  | Wed
  | Thu
  | Fri
  | Sat
  | Sun
  deriving (Eq, Show)
```

## Dispatched by type

> Type classes are defined by the set of operations and values all instances will provide. Type class instances are unique pairings of the type class and a type. They define the ways to implement the type class methods for that type.

> The class definition doesn’t define any terms or code we can compile and execute, only types. The code lives in the instances.

This means the compiler needs to know what types are involved in the operation defined by a type class and then use the implementation defined by those types. Haskell being lazy will delay this as much as possible.

## Conclusions

Type classes are Haskell's approach to polymorphism and one of it's killer features. Not only it avoids [inheritance problems](https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem)! :tada: but type classes are a very powerful way of constraining operations to certain types without coupling the types to the operations (like objects do).

The chapter mentioned a few more things about type classes, but this should already give a good practical idea of what type classes are.

P.S.: Don't know why I chose the pizza picture, but now you are hungry too.

[^1]: Philip Wadler, “The Expression Problem” http://homepages.inf.ed.ac.uk/wadler/papers/expression/expression.txt