We don’t usually give much thought to Numeric data types beyond whether we want to work with integers or decimal numbers. And that is a shame! In this post I’ll look at how we can actually do arithmetic operations lazily, and in the process hopefully reveal a bit about haskell’s numeric classes.

```
module LazyArithmetic
where
```

We will be using
Lennart Augustsson’s `numbers`

library which can be
installed from hackage with
cabal-install:

```
$ cabal install numbers
```

import these libs:

```
import Data.Number.Natural
import Data.List(genericLength)
```

Consider two functions: the Prelude function `sum`

and `genericLength`

from
the List library:

```
genericLength :: (Num i) => [b] -> i
sum :: (Num a) => [a] -> a
```

…two simple functions that have the potential to be very expensive, depending on the length of the list and the values of the elements. Say for instance that all we want is to use:

```
sumLengths = sum . map genericLength
checkLengths as n = (sumLengths as `div` n) > 2
```

The `checkLengths`

function above has to count every element of every element
of every sub-list in order to return a `Bool`

value, and if any of those lists
are infinite our program will never terminate:

```
hopeless = checkLengths [['a'..'z'], ['0'], repeat 'Z'] 99
```

*…or so we might think!*

### Lazy Natural Numbers

It turns out we can solve our seemingly hopeless situation with a type signature:

```
sumLengths :: [[b]] -> Natural
```

And suddenly, as if by magic:

```
*LazyArithmetic> hopeless True
```

What’s going on here? Well it turns out the problem is that Haskell’s built-in numeric types are boring, old-fashioned and (in some cases) just plain wrong. But let’s step behind the curtain and look at how the Data.Numbers library defines the Natural type internally:

```
data Natural = Z | S Natural
```

We see that we’re using an abstract data type to represent non-negative
integers, and it looks nearly identical to our list type `[]`

. The upshot of
that is we gain, in our numeric type and arithmetic operations, the same type
of laziness that lists afford us!

So in the above example, `hopeless`

, we need only carry out the operations far
enough to see that the result is `> 2`

.

The numeric type in `Data.List.Natural`

are actually known as
Peano numbers. They are
essentially just lists of units and, as you might imagine, are not the most
efficient way to represent an integer.

But they are exactly what we want for this application. If we failed to realize that we could solve our problem with an appropriate numeric representation, we might try to rig up something like this:

```
checkLengthsUnclear as n = not $ null $ drop (n*2) $ concat as
```

…which works identically to `checkLengths`

with Peano Numbers, but
completely obfuscates the intention of the function. As usual laziness gives
us *expressive power* rather than an efficiency boost.

### Limitations, Haskell’s Numeric Type Classes, and the Numeric Prelude

The `Data.Number.Natural`

library is convenient because it provides Num and
Integral instances so we can use the the Natural type with any function that
is polymorphic on those classes.

The problem is the Num instance is incomplete
and error-prone: and that’s because a
natural number type *shouldn’t be an
instance of Num*! We can’t negate a Natural, which in turn makes subtraction
dangerous, etc.

```
*LazyArithmetic> let x = 1 :: Natural; y = 2 in x - y
*** Exception: Natural: (-)
```

We might wish that haskell’s Numeric type classes were more expressive, allowing for more abstract numeric types. For example it might be more “haskelly” for the length function to be defined with the type:

```
length :: Natural n => [a] -> n
```

After all we don’t use integers for boolean values as in C; we have the
abstract type `Bool`

. So why return an Int when a Natural type (or class)
might be more expressive? The answer of course is that that gets really
complicated really fast.

For one approach at making haskell’s numeric class hierarchy more expressive and flexible, check out the Numeric Prelude. It’s haddock documentation is very thorough and an interesting read, and you can see the sheer number of design decisions necessary for such an undertaking.

For some other approaches and links, see here.