---
title: "Multiple Typeclass Instances using Newtype in Haskell"
date: 2022-04-28T23:09:42-07:00
expirydate: 2022-04-28T23:09:42-07:00
tags: ["Haskell"]
draft: true
---

> And I have known the eyes already, known them all—
>
> The eyes that fix you in a formulated phrase . . .

It sometimes feels like the data types that we work with are simply
too locked down through their typeclass instances. A type might have multiple
law-abiding implementations of the required methods, and yet only one implementation can be used
in an `instance` declaration. First, let's take a look at some type classes and types
for which this is true, starting with `Monoid`.

### The `Monoid` Type Class
Recall that for a type `m` with `Monoid m`, the following things are available:

* An associative binary operation, `(<>)`. Associativity means that for any
  three elements of `m`, like `a`, `b`, and `c`, the following
  holds:

  ```Haskell
  (a <> b) <> c == a <> (b <> c)
  ```
* An neutral element under `(<>)`, called `mempty`. It being the neutral element
  means that using it with `(<>)` doesn't do anything. For any `a :: m`, we
  can (with minor notation abuse) write the following:

  ```Haskell
  a <> mempty == mempty <> a == a
  ```

This is a pretty broad specification, actually. Many types have multiple different
operations that satisfy the `Monoid` laws. Let's take a look at a few of them,
starting with integers.

#### Integers
Addition is an associative binary operation. Furthermore, it's well-known that adding zero to a
number leaves that number intact: \(0+n = n + 0 = n\). So we might define a `Monoid` instance for
numbers as follows. Note that we actually provide `(<>)` via the `Semigroup` class,
which _just_ requires the associative binary operation, and serves as a superclass for `Monoid`.

```Haskell
instance Semigroup Int where
    (<>) = (+)

instance Monoid Int where
    mempty = 0
```

Cool and good. But hey, there are other binary operations on integers! What about
multiplication? It is also associative, and again it is well-known that multiplying
anything by one leaves that number as it was: \(1\*n = n\*1 = n\). The corresponding
`Monoid` instance would be something like the following:

```Haskell
instance Semigroup Int where
    (<>) = (*)

instance Monoid Int where
    mempty = 1
```

But we can't have both. Haskell yells at us:

```
Duplicate instance declarations:
  instance Semigroup Int -- Defined at test.hs:1:10
  instance Semigroup Int -- Defined at test.hs:7:10

Duplicate instance declarations:
  instance Monoid Int -- Defined at test.hs:4:10
  instance Monoid Int -- Defined at test.hs:10:10
```

Okay, so we can have at most one. But that's not good.
Fortunately, thanks to the `Num` instance for `Int`, we get
functions that are pretty much the same as `fold`, except
specialized to multiplication and addition:

```Haskell
fold :: (Foldable t, Monoid m) => t m -> m
product :: (Foldable t, Num a) => t a -> a
sum :: (Foldable t, Num a) => t a -> a
```

This takes care of _most_ of the uses we have for `(+)` and `(*)`;
it does, however, prevent us from using `Int` with [`MonadWriter`](https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Writer-Lazy.html#t:MonadWriter).

#### Booleans
