So Iāve been thinking about this a lot, because itās something that I want in theory, to the point where Iāve already implemented over a half dozen float wrapper types in my own code. However, Iām skeptical that it will be ergonomic, and Iād like to outline what I think the basis of that is.
If we take a look at String, we can see it as a wrapper around Vec<u8> that maintains a UTF-8 invariant, but in practice that is not all that it is, and Iād argue that it is not enough to only do that. The difference is that String provides a complete suite of total (as in non-partial) methods for manipulating UTF-8 data. Iām imagining what I would be doing if it didnāt: Iād likely use Vec as an āASCIIā type and convert to String only when I wanted/needed to verify it as UTF-8.
EDIT: Actually, the property Iām referring to above should be closure, not totality/partiality.
Anyway, the problem Iāve always had with my own float wrappers is that float operations are almost all partial, so youāve got to exclude them (consider /=, for instance), or āescapeā your wrapper type, which hurts ergonomics by making you re-wrap. And in practice, Iāve gotten so frustrated with this that I only use them for Ord now. (Thereās a similar level of frustration around as.) The trouble here being that this encourages you to only use these wrapper types at API boundaries, where an assertion would do just as well.
Maybe something could be done by introducing a whole zoo of wrapper types (Finite, NonZero, NonNan, NonNegative), but I feel like these will all have the same essential problem, and itās not clear to me that we are doing anything but re-implementing float semantics at that point.
The ergonomic loss here is not in calling the div function, but in how you get your FiniteNumber and FiniteNonZeroNumber values. Calling the constructors for those types is no better than asserting that your denominator is nonzero. Itās potentially even worse. Sure, your div never panics, but your FiniteNumber constructor does⦠so weāre just pushing panics around unless you can statically determine all of your input values. And if you can do that, then just do CTFE and give a compiler error when a panic would occur.