Why does rust not define a Numeric trait?

Desired use case:

struct MyType {
    // Members
}
// Numeric is a trait provided by rust-lang and it implies that
// the implementing type is an algebraic field
impl Numeric for MyType {
    // Behaviour implementation
}

While there is a crate rust-num having contributors from the core team as well, it is not a part of the mainline.

Having the language provide such abstractions would be pretty handy for creating custom generic types for algebraic fields. This would cover a lot of number crunching use-cases (data-analysis, quant-finance, computer graphics etc) and Rust is more likely to be used in such environments as against, say, CRUD systems where higher level languages may have advantages.

Furthermore, digging into the source code of Rust itself, we see a lot of macros like the one here for addition which could be replaced by the trait having default implementation of behaviours.

Thoughts?

PS: I am not very familiar about what kind of trade-offs are faced when implementing at such low level and may be there are (or were) constraints which led to the current state.

Update-1: From a strict mathematical perspective, integers are an algebraic group ring but many programming languages (including Rust) implement them as a field with overflow and/or cast (or truncate) constraints for division.

These cannot be implemented with a default blanket impl bounded by a trait due to trait coherence rules. The blanket impl would conflict with most other impls.

There are quite a lot of crates like this, other notable ones are rand, regex, and serde. All of these would have been in the std of another language, but Rust likes to keep it's std small and keep crates.io as the batteries that would have been included in other languages.

num used to be in the std prioir to 1.0, but was removed because it's api wasn't well formed yet. I'm not sure why it isn't in the std now, but is quite a big project on it's own.

Keeping it out of std allows it to develop at it's own pace and develop better apis faster. This also allows num to do breaking changes when something goes wrong, and putting it is std would force us to live with bad apis.


A way forward is to propose a minimal set of traits that can be included in std.

7 Likes

Thanks for the reply! Is there an authoritative document for the coherence rules? A quick search returns lot of non-authoritative sources.

https://github.com/Ixrec/rust-orphan-rules is my attempt at an unofficial summary providing links to all of the official, authoritative sources while putting them in proper context. To quote the part that answers your question:

The precise statement of the orphan rules is rather technical because of generics like impl Trait<Foo, Bar> for Type<Baz, Quux> (see "Little Orphan Impls"), and the #[fundamental] attribute, and OIBITs/auto traits, and probably something else I'm forgetting about. Today, I believe the most official and up to date precise statement of the orphan rules is RFC #2451, accepted in October 2018 and implemented in January 2019.

Most Rustaceans stick to the simplification that "either the type or trait must be from the same crate" since it's very easy to remember and is accurate in the most typical cases.

5 Likes

Is/was there a plan to have them return to the std-lib?

For some context, there were, I believe, three or four attempts at defining a numeric trait hierarchy before Rust 1.0. All of them had problems, and so that's why we didn't ship.

Some issues, over time:

I cannot find the bit about actually removing them, though! I thought it was that RFC, but apparently not quite.

5 Likes

Thanks for sharing those links. They provide helpful context. Going through them and other answers in this thread, it seems that part of the problem with original numeric hierarchy was in conflating operations on numeric types with calculations involving such types and their operations.