@bharvey wrote,
The acid test is whether your language considers 3.0 to be an integer. The only right answer to that question is "yes."
He was criticizing type systems where 3.0 : float
but not 3.0 : int
. That got me thinking, when we learn math, we think of the real numbers being a superset of the rationals, which are a superset of the integers, which are a superset of the naturals, etc. However, when using mathematically oriented programming languages, the sets of numbers do not have a subtyping relationship, because from a formal point of view, they are different constructions. One defines them, like the naturals here:
data Nat : Type where
Z : Nat
S : Nat -> Nat
Then, one defines integers, rationals, and so on.
According to Integer - Wikipedia, one can define the integers as a pair of natural numbers along with an equivalence relation (a, b) ~ (c, d)
that is true when a + d = b + c
. The section adds that automated theorem provers might use other definitions, and agda-stdlib/src/Data/Integer/Base.agda at f2744a829ea7dbef68aa15e7c549485c112ddfb7 · agda/agda-stdlib · GitHub shows that Agda defines integers to either be a "positive" Nat or a "negative" of one more than a Nat.
According to https://en.wikipedia.org/wiki/Rational_number#Formal_construction, one can define the rationals as a pair of integers as well as an equivalence relation (a, b) ~ (c, d)
that is true when a * d = b * c
.
We like to think that 3 as an integer and 3 as a rational are the same 3, but with these formal constructions, (S (S (S Z), Z) : Int
is different from ((S (S (S Z), Z), (S Z, Z)) : Rat
. It wouldn't make sense to write ((S (S (S Z), Z), (S Z, Z)) : Int
.
We give a semantic meaning to the rationals that causes us to consider them to be a superset of the integers. Indeed, there exists a function from Int
to Rat
that specifies this semantic meaning. However, there also exists a function from Bool
to Char
, yet we don't consider Bool
to be a subset of Char
. Bool
and Char
are different, and likewise, Int
and Rat
are different.
With upcasting, maybe one can have an implicit "conversion" function. However, for downcasting, such a function would be partial (a no-no for good programming style as well as for proof soundness). My main point is that the belief that the rationals is a superset of the integers such that some rational numbers should have the type of "integer" isn't logical. Whether we are dealing with machine arithmetic or formal mathematical definitions, the different sets of numbers have different representations that should correspond with different types.
In set theory or type theory, how often does one make the distinction between 3 the integer and 3 the rational, and when would one consider the rationals to be a superset of the integers?