4

So I have been reading, how you can convert ADTs into what resembles Real numbers and manipulating them, on pages like this SO question and this 3 part series and especially this.

The "Trouble" section of the last link caught my eyes and I tried to solve for Nat in it even though the article states it's impossible.

Nat = 1 + Nat
Nat - Nat = 1
Nat(1 - 1) = 1
Nat = 1 / (1 - 1)

This might seem like total nonsense since I just divided by 0 (and you might be right), but if you read any of those links or something similar, then you'll notice that it looks very similar to a definition of a list.

List(x) = 1 / (1 - x)

So you could write Nat like Nat = List(1) = 1 + 1 + 1 + ..., which is exactly what you would get by repeated substitution in the starting equation. This is also equivalent to defining Natural numbers like this in Haskell:

type Nat = [()]

Which is definitely a valid encoding of Natural numbers, where 0 = [] and S(N) = () : N.


So my question is how come did I get a valid result out of this? I just divided by zero. Not to mention the starting equation itself is pretty much a contradiction.

So how come I got something that makes sense at the end of this? Is this just pure coincidence or is the division by 0 somehow defined in this context that makes sense?

Community
  • 1
  • 1
The Red Fox
  • 810
  • 6
  • 12
  • Strictly speaking, `1 != 1*1`, so it would be more correct to write `Nat = 1 + 1*1 + 1*1*1 + ...`. – chepner Sep 28 '16 at 14:59
  • @chepner can you please explain why? The way I understood it, types form a semiring, where `1` is the identity of `*`. In other words `x * 1 = 1` for any x. So `1` and `1*1` are equivalent. – The Red Fox Sep 28 '16 at 15:07
  • They are *isomorphic*, not equivalent. The ordered pair `((), ())` is distinct from the `()`. `x * 1 == x` because you can losslessly convert a value `(a, ()) :: (x,())` to `a :: x` and vice versa. – chepner Sep 28 '16 at 15:15
  • 3
    @chepner, all these kinds of manipulations are (at best) up to isomorphism anyways. Just read `=` as "is isomorphic to" if you like. – Reid Barton Sep 28 '16 at 15:20
  • I think the answer is probably that you only did manipulations that you also could have done with List(x), but writing 1 instead of x. But it's not clear to me that there is a real question here. – Reid Barton Sep 28 '16 at 15:21

1 Answers1

1

Since Nat is infinite, you can't really use Nat - Nat = Nat ⋅ (1 - 1) = Nat ⋅ 0 = 0. The difference Nat - Nat is some finite number, as it were, whereas Nat is obviously infinite. So this 1 - 1 isn't really zero, it's rather like an infinitesimally small value in nonstandard analysis. If you divide something by an infinitesimal, you get something divergingly big (infinite, indeed... duh), but you don't exactly run into division-by zero.

In fact, I think that paradox you asked about could be seen as a “proof that Nat is infinite” – because if it were finite, you would be dividing by zero.

Except of course you can't really prove anything with this kind of type arithmetic... it's an entertaining pastime, but not really sound mathematics.

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • Not with this sort, no, but with more careful sorts (difference calculus stuff) you surely can. – dfeuer Sep 28 '16 at 18:21