I demonstrated how to make kilobyte/megabyte constants in Haskell and a Lobsters user asked how it worked. This is a bloggification of my reply to them explaining the trick.

The original code:

```data Bytes =
B
| KB
| MB

instance (b ~ Double) => Num (Bytes -> b) where
fromInteger i B =
fromInteger i
fromInteger i KB =
fromInteger \$ i * 1024
fromInteger i MB =
fromInteger \$ i * 1024 * 1024

instance (b ~ Double) => Fractional (Bytes -> b) where
fromRational r B =
fromRational r
fromRational r KB =
fromRational \$ r * 1024
fromRational r MB =
fromRational \$ r * 1024 * 1024
```

Using this from the REPL:

```Prelude> 100 B
100.0
Prelude> 100 KB
102400.0
Prelude> 100 MB
1.048576e8
```

Do you need any language extensions?

You need flexible instances and `~`, usually from `TypeFamilies`. These are things I have turned on by default in all of my application projects.

Would you mind explaining a bit more in detail how it works?

Warning: This explanation won't work great if you know literally zero Haskell. If that's the case, uhhhh, buy my book?

The `Num` and `Fractional` type classes are the basis for integral and fractional literals in Haskell. Every numeric literal in Haskell is polymorphic until the instance is resolved to a concrete type. `1 :: Num a => a` and `1.0 :: Fractional a => a`, where `::` is type ascription and can be read as "has type."

The `(b ~ Double)` isn't strictly necessary if you don't care about type inference. You could elide it and then the examples would look like:

```Prelude> 100 B :: Double
```

The essence of it is in the weird shape of the instance type: `Num (Bytes -> b)`. We're making an instance for numerical literals that is function-typed. We've said the inputs must be values from our `Bytes` type. This makes it so that in the expression: `100 B`, the `100` gets resolved to a function which multiples the underlying number by the magnitude expressed in the data constructor passed to it as an argument, be it `B`, `KB`, or whatever else.

Now, hypothetically, we might know that we always want `Bytes -> Double`. If we don't care about type inference, then our instance can be pretty simple:

```instance Num (Bytes -> Double) where
```

And we're done, but that didn't satisfy me. I wanted to see if I could get fancy syntax. If you try it unqualified, you get:

```Prelude> 100 KB

<interactive>:7:1: error:
• No instance for (Num (Bytes -> ())) arising from a use of ‘it’
(maybe you haven't applied a function to enough arguments?)
• In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
```

GHCi will default the return type to `()` when the instance head is `Bytes -> Double`. So the stages of evolution are:

```Bytes -> Double
Bytes -> b
(b ~ Double) => Bytes -> b
```

The weird part is, `(b ~ Double) => Bytes -> b` and `Bytes -> Double` are the same type. `b ~ Double` just means, "b is `Double`". However, that part of the type-checker runs at a different time than instance resolution.

What we really want is "instance local functional dependencies" and that's exactly what this trick accomplishes. See more about functional dependencies here: https://wiki.haskell.org/Functional_dependencies

What the type `(b ~ Double) => Bytes -> b` lets us do is "capture" uses of function-typed numerical literals whose inputs are `Bytes` and that have a return type whose type is unknown, then we supply a concrete type for the return type with the type equality `b ~ Double` after the instance is already resolved.

You can't overlap them:

```Duplicate instance declarations:
instance (b ~ Double) => Num (Bytes -> b)
-- Defined at /home/callen/work/units/src/Lib.hs:40:10
instance (b ~ Integer) => Num (Bytes -> b)
-- Defined at /home/callen/work/units/src/Lib.hs:49:10
```

But if the input types are different, totally kosher:

```data Bytes =
B
| KB
| MB

instance (b ~ Double) => Num (Bytes -> b) where
fromInteger i B =
fromInteger i
fromInteger i KB =
fromInteger \$ i * 1024
fromInteger i MB =
fromInteger \$ i * 1024 * 1024

data BytesI =
Bi
| KBi
| MBi

instance (b ~ Integer) => Num (BytesI -> b) where
fromInteger i Bi =
i
fromInteger i KBi =
i * 1024
fromInteger i MBi =
i * 1024 * 1024
```
```Prelude> 100 B
100.0
Prelude> 100 Bi
100
```

## Prior art

The irony of this method given the "fundeps vs. type families" debate is that instance local functional dependencies are achieved using a mechanism introduced by type families.