rust-num / num-integer

Integer trait and functions for Rust
Apache License 2.0
180 stars 48 forks source link

Wrapper types? #63

Closed Rudxain closed 7 months ago

Rudxain commented 7 months ago

Taking inspiration from NonZero<T> and Type-driven parsing, what if this crate (or a separate one, for organizing) provided wrappers for specific numeric properties?

Strawman examples (not tested as compilable):

#[derive(Deref)]
struct Even<T: Integer>(T);

impl<T: Integer> even for Even{
    fn new(x: T) -> Option<Self> {
        if x.is_even() {Some(Self(x))} else {None}
    }
}
// assume `Odd` is defined similarly...

impl<T> Add for Even<T> {
    // even + even = even
    fn add(self, &Self) -> Self
    // even + odd = odd
    fn add(self, &Odd) -> Odd
}
// etc... assume Odd also has similar methods which follow the theorems of math

New fns could be defined that take advantage of such types. If a fn requires a Prime to work properly and safely, it'll no longer have to check primality by itself!

The compiler could optimize code using Even or Odd to have the same size and alignment as Option<Even | Odd> (because LSB is unused).

Existing fns could use these types to guarantee stuff such as

fn sqrt(n: Square<u64>) -> u32

// this equality will be satisfied for all `Square`s!
assert_eq!(sqrt(Square::new(4).unwrap()).pow(2), 4)

If num provided such types, there would be less crates implementing their own wrappers, or worse, doing redundant expensive checks:

use crate1::Prime1;
use crate2::Prime2;
use crate3::CheckedPrime;

crate1::some_fn(Prime1::new(5).unwrap())
crate2::another_fn(Prime2::new(5).unwrap())
crate3::some_fn(CheckedPrime::build(5).unwrap())

If there was 1:

use num_integer::Prime;

let p = Prime::new(5).unwrap();

// assuming all crates have chosen `num` as standard
crate1::new_fn(p)
crate2::yet_another_fn(p)
crate3::foobar_fn(p)
Rudxain commented 7 months ago

I've been considering that, perhaps, this would be more appropriate for something like ranged-ints/deranged rather than num

cuviper commented 7 months ago

If multiple other crates have a shared need for some wrapper, they can collaborate on a common crate, but I definitely don't want to get into implementing all possible number categories here. :)

Rudxain commented 7 months ago

they can collaborate on a common crate

good point 👍

definitely don't want to get into implementing all possible number categories here. :)

I totally agree! haha. There's literally infinite of them. Even niche ones such as Fib, and AFAIK, it's extremely rare to find an algorithm that requires Fibonacci numbers (maybe Fib Trees?).

I propose we only focus on simple, everyday stuff, such as Even & Odd. There's no need to impl operator traits, as Deref can be used to implicitly operate on them as regular ints

cuviper commented 7 months ago

Honestly, I'd rather see even the simple stuff developed in their own crate. If it needs small additions in num-integer (not breaking changes), that might be accommodated, but this isn't a good place for big new experiments.

Rudxain commented 7 months ago

this isn't a good place for big new experiments

I agree, especially considering rust-num/num#421