☯ @lisp #00: Numeric Tower


So, many of you may be familiar with the ol’ set of numbers that are present in nearly every language:

But some languages go beyond this, and I mean wayyy beyond.. time to say hi to the numeric tower.

From math we know the classic ℕ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ. Put into words, we have complex numbers, some of which are real, some of those are rationals, etc. all the way down to naturals. This is slightly complicated by our computer friends since there’s more than one way to represent any number, so your standard C-like int doesn’t really contain much of the infinite expanse of naturals let alone integers, our poor 32 bits can only go so far. Which nonetheless is itself not invalid, just that C integers are actually a ℤ₃₂ division ring, well unless we trap the overflow and signal an exception, which is what some other languages do, Rust taking an interesting route of doing the latter in Debug mode and then the former in Release mode for performance’s sake. Nonetheless width isn’t the only thing, floating point numbers can also act as some integers, as can rationals, and there’s always the question of which should fall out the other end when dividing, or even if non-whole results should be an empty optional type.

All this is to say that for the purpose of programming languages, numbers have more properties than is at first apparent, or even implemented in many languages at this moment.

So our types should be able to describe both what their representation is, what forms they take when being operated on, and preferably more for optimization and extra verification. Well, that’s a lot of work for a lonely little type, which is why these are usually arranged into a sort of lattice form of relations that the values dynamically traverse.

All-in-all there’s a few properties then:

Seems complex numbers are usually not a problem except when it comes to ordering, which causes the awkward interaction that Ord is only applicable to Reals as far as I can tell. Which seems consitent with what Common Lisp does.

This does sort of imply that some operations like sqrt have either NonNegative → NonNegative or Negative → Complex as their type…

Keeping some information can also help with optimizations, for example when having a fixnum (which is what Lisp calls numbers that have a bounded number of bits) addition, i.e. we know the result is a fixnum, then we can forego all manner of overflow checking, checking if the inputs are integers or rationals, etc.

I wondered if some sort of, Tower <Rational-Type> <Complex-Handling> scheme could be useful, along with of course the classic Integer <Min> <Max>, but I’m not sure how useful this would be.

What I’m thinking we could end up with is a sort of, Tower algebraic effect, that provides the basic arithmetic operators based on what the given preferences are.