[Solved] Implement trait for structs, types, tuples, vectors, etc

#1

I am starting a library for calculus in Rust named Horse-Shoe and I am currently programming the first asset. I’ve created a trait for parametric types that has a numerical differentiation function. Succeeding in doing it for types I knew that my job wasn’t done because numerical differentiation also implements complex numbers, vectors and multiple parameter valued functions. The problems starts rising here. If i try to do the implementations (yes, I know about macro rules, but it was for example purposes) like this, it shows three error[E0053]:

method numder has an incompatible type for trait

What I kneed to do to just make it work?
And If you happen to know that this thing is currently impossible in Rust, please comment it.

#2

I’m a bit confused about your intent with the Diff trait:

pub trait Diff<T: FromPrimitive + Num> {
    fn numder(z: T, f: &Fn(T) -> T, i: i8) -> T {
        let h = T::from_f64(1e-10).unwrap();
        (f(z + h) - f(z)) / h
    }
}

Since to be used, a trait has to be implemented for a certain type, there should be something about the trait that ties it to the particular type. Either the functions defined by the trait should use Self or self somewhere or there should be functions that have no default implementation. If neither of those are true, you might as well just use a generic function like

    fn numder<T: FromPrimitive + Num>(z: T, f: &Fn(T) -> T, i: i8) -> T {
        let h = T::from_f64(1e-10).unwrap();
        (f(z + h) - f(z)) / h
    }

If you want to use a trait, instead of adding a generic type parameter, reference the Self type:

pub trait Diff where Self: FromPrimitive + Num + Copy {
    fn numder(self, f: &Fn(Self) -> Self, i: i8) -> Self {
        let h = Self::from_f64(1e-10).unwrap();
        (f(self + h) - f(self)) / h
    }
}

Additionally, to get things to build, I added a trait bound for Copy. Alternatively, you could make numder take a &self parameter, but then you’d need to make sure std::ops::Add is implemented for &Self. For now, let’s keep it simple and only deal with Copy types.

With that definition of the Diff trait, we can implement it for Complex<T> and f64:

impl<T> Diff for Complex<T> where T: Copy + nt::Num + FromPrimitive {}
impl Diff for f64 {}

Though Vec<T> won’t be so simple. You’ll probably want to use different traits for numbers and collections of numbers.

There are some other issues with the code that I think will make sense when you see the compilation errors, but hopefully this is enough to help get you un-stuck.

1 Like
#3

A bit different turn on @baumanj’s approach, I added a Target associated type which allows for (T, T)'s anomaly and there are a few type constraints that need to be ironed out with the ops.
Playground

Here’s a fixed playground but it still doesn’t compile as the implementation for Vec is a bit illogical.

1 Like
#4

Thanks to you for your help, I’ve nailed with complex numbers and real ones :heavy_heart_exclamation: