Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrapper types? #63

Closed
Rudxain opened this issue Apr 12, 2024 · 5 comments
Closed

Wrapper types? #63

Rudxain opened this issue Apr 12, 2024 · 5 comments

Comments

@Rudxain
Copy link

Rudxain commented Apr 12, 2024

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 can 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
Copy link
Author

Rudxain commented Apr 12, 2024

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

@cuviper
Copy link
Member

cuviper commented Apr 12, 2024

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
Copy link
Author

Rudxain commented Apr 13, 2024

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
Copy link
Member

cuviper commented Apr 15, 2024

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.

@cuviper cuviper closed this as completed Apr 15, 2024
@Rudxain
Copy link
Author

Rudxain commented Apr 15, 2024

this isn't a good place for big new experiments

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants