Hi @alexandrehsaad.
I have to confess that I'm a little bit torn about this. It's a very well-written proposal for a feature that I don't really want to have. To paraphrase Ben, rationals are the linked lists of numerics. There's a very narrow set of situations in which they're a good option, but that set of situations is vastly more limited than most people think it is. I've written about their drawbacks a few times, but to paraphrase:
- If you round results, it is always strictly better to use floating-point, because it has scale invariance and fewer redundant representations, so for any fixed precision it has smaller error.
- If you do not round results, the sizes of the numerator and denominator grow exponentially in general.
- Because of this, any non-trivial fixed-size rational program overflows immediately.
All that said, this is generally a well-written proposal, and rational types do have some limited uses, so I'm willing to mentor this if we narrow the scope a little bit. Specific feedback:
-
You don't need a protocol. You need a generic type
Rational<Term>
(or yourFraction<Term>
). At some future point, there might be a reason to create a protocol, but you need to start with the concrete type and build from there. -
There's probably no reason to include a NaN representation for rationals. Infinity is likely also unnecessary.
-
You should simply require canonicalization (simplification). I'm open to being convinced otherwise, but this is generally the correct approach, and eliminates the need for
RationalSimplifiable
. -
MixedFraction
isn't a separate type, it's a presentation ofFraction
. -
Continued fractions are a whole separate thing, with a very different set of uses. They're worth investigating, but are probably their own separate project.
-
Percentage is probably a string presentation on
Fraction
andFloatingPoint
, rather than its own type. In particular, limiting to whole-number percentages is undesirable for a wide variety of reasons; we would especially not want people to convert to a percentage, changing the value, and then use that value for further computations. This is why it makes the most sense to have this be a presentation instead of a numeric type. If I have 363/1000 and 633/1000 and 4/1000, converting those to whole-number percentages and then adding would yield 99%, instead of the correct 100%; we want to prevent that. -
One of the more interesting and useful features that you should include is the ability to produce a "close" approximation of a FloatingPoint value with a rational, using continued fractions.
If you still want to move forward with this, feel free to reach out to me with an updated draft (I know that time is short, so you don't have to incorporate all of my feedback--what I'm mainly interested in is knowing that you're OK with this slight redirection.)