# Type Classes and Instances — Haskell

Source: https://www.geekswithgeeks.com/en/haskell/t-classes

> Use and define type classes, derive instances and understand constraints.

## Ad hoc polymorphism

A **type class** declares operations that types can support, like an interface: `class Show a where show :: a -> String`. An **instance** provides the implementation for a specific type: `instance Show Paise where ...`. Functions use **constraints** to require capabilities: `maximum :: Ord a => [a] -> a` works for any ordered type. Common classes: **`Eq`** (`==`), **`Ord`** (`compare`, `<`), **`Show`** (debug strings), **`Read`** (parsing, best avoided for user input), **`Num`**, **`Integral`**, **`Fractional`**, **`Enum`**, **`Bounded`**, **`Semigroup`** (`<>`) and **`Monoid`** (`mempty`), and the structural classes **`Functor`**, **`Foldable`**, **`Traversable`**, **`Applicative`** and **`Monad`**. Many instances can be **derived** automatically (`deriving (Show, Eq, Ord)`), and extensions such as `DeriveGeneric`, `DeriveAnyClass` and `DerivingVia` derive more. Classes can have **default methods** and **superclasses** (`class Eq a => Ord a`). Unlike interfaces in OOP, instances can be added to existing types after the fact, but avoid **orphan instances** (instances defined in neither the class's nor the type's module), which can conflict.

## Defining a class and instances

A HasArea class, a custom Show and a Monoid for money.

```haskell
data Shape = Circle Double | Rect Double Double
  deriving (Show, Eq)

class HasArea a where
  area :: a -> Double
  describe :: a -> String
  describe x = "area " ++ show (area x)          -- default method

instance HasArea Shape where
  area (Circle r) = pi * r * r
  area (Rect w h) = w * h

newtype Paise = Paise Int
  deriving (Eq, Ord)

instance Show Paise where
  show (Paise p) = "Rs " ++ show (p `div` 100) ++ "." ++ pad (p `mod` 100)
    where
      pad n = if n < 10 then '0' : show n else show n

instance Semigroup Paise where
  Paise a <> Paise b = Paise (a + b)

instance Monoid Paise where
  mempty = Paise 0

largestArea :: HasArea a => [a] -> Double
largestArea = maximum . (0 :) . map area

main :: IO ()
main = do
  putStrLn (describe (Rect 3 4))                   -- area 12.0
  print (largestArea [Circle 1, Rect 2 5])         -- 10.0
  print (mconcat [Paise 4950, Paise 19900, Paise 5])   -- Rs 248.55
  print (maximum [Paise 300, Paise 120])           -- Rs 3.00
```

## Job qualifications

A type class is a qualification such as "can drive". A function that needs a driver states the constraint (Drives a =>) without caring who it is, and each type proves it holds the qualification by providing an instance.

**Quiz:** What does the constraint in `sort :: Ord a => [a] -> [a]` mean?

- [ ] a must be a list
- [ ] a must be Int
- [ ] sort returns an Ord
- [x] sort works for any type a that has an Ord instance

*Answer:* sort works for any type a that has an Ord instance. Constraints restrict type variables to types with the required instances.
