Negative bound trait

How can I design an "apply" function that will apply a function to each of its element or if the element itself implemented Apply trait, call the apply function.

it seems that negative trait bound is not supported, so I can not express T : !Apply<T, F>

and also I have to use apply, apply2 instead of using one name for this function.

pub trait Apply<T, F> where F : Fn(&T) -> T {
    fn apply(&self, f : F) -> Self;
}

impl<T, F> Apply<T, F> for Vec<T> where F : Fn(&T) -> T {
    fn apply(&self, f : F) -> Vec<T> {
        self.iter().map(|x| f(x)).collect()
    }
}

pub trait Apply2<T, A, F> where F : Fn(&T) -> T, A : Apply<T, F> {
    fn apply2(&self, f : F) -> Self;
}

// impl<T, F> Apply<T, F> for Vec<T> where F : Fn(&T) -> T, T : !Apply<T, F> {
//     fn apply(&self, f : F) -> Vec<T> {
//         self.iter().map(|x| f(x)).collect()
//     }
// }

impl<T, A, F> Apply2<T, A, F> for Vec<A> where F : Copy + Fn(&T) -> T, A : Apply<T, F> {
    fn apply2(&self, f : F) -> Vec<A> {
        self.into_iter().map(|x| x.apply(f)).collect()
    }
}

#[test]
fn main() {
    let v1 = vec![1, 2, 3];
    let v2 = v1.apply(|x| x * x);
    println!("{:?}", v2);

    let v1 = vec![vec![1,2,3], vec![4,5], vec![6]];
    let v2 = v1.apply2(|x| x * x); // how can I change this to apply instead of apply2?
    println!("{:?}", v2);
}

You can share the method name by using the (unfortunate) fully qualified syntax, but it's not really any better:

let v2 = Apply2::apply(&v1, |x| x * x);

Unfortunately, the general solution your looking for is specialization, which Rust doesn't support (on stable).

There's a few hacks and workarounds if you search, but I'm not sure which, if any, would be best here.

is there some solution for nightly version?

This works but requires an annotation on the nested version's closure.

This is pretty much the same, but with a more idiotmatic signature IMO.

I'm not sure if it covers your actual use case or not, since the Vec<Vec<T>> implementation is no longer generic (Vec<A>).

Looks like you can use the #![feature(min_specialization)] and #[rustc_specialization_trait] attribute: here's the docs for std developers: Specialization - Standard library developers Guide

Thanks, but such solution only work for Vec<Vec>, I'm looking for a more generic way, this is the function that I want to have (maybe I should call this method map instead):

1 Like

You could approximate the levelspec like so, but would need an implementation per level I believe. There might be a recursive solution using something like typenum instead of const generics (but I didn't try).

Thanks, I will use this solution, I can use some macro to reduce code for different levels.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.