Impl trait for F where F can be different variations of Fn


#1

Stepped on a issue with traits and functions, where I have conflicting implementations of a trait.

While I can implement a trait that executes a function like this in Rust:

trait Foo<T> {
    fn bar(self) -> T;
}

impl<T, F> Foo<T> for F
where
    T: Float,
    F: Fn(T) -> T,
{
    fn bar(self) -> T {
        self(T::one())
    }
}

fn spam(eggs: f64) -> f64 {
    eggs.ln()
}

fn main() {
    println!("{}", spam.bar());
}

I cannot do the same stuff again for another function (i.e: Fn(T, u8) -> Struct<T>) like this:

impl<T, F> Foo for F
where
    F: Fn(T, u8) -> Struct<T>
{
    // Stuff
}

That will conflict with the first implementation, and I don’t want to delete the former or create two traits. What I the only thing I wanna do is adding more implementations for the types:

  • Fn(T, u8) -> Struct<T>
  • Fn(T) -> OtherSt<T>
  • Fn(T, T) -> T
  • etc.

#2

two ways to go about this, both with their own problems

1

change over to using function pointers

trait Foo<T> {
    fn bar(self) -> T;
}

impl<T, F> Foo<T> for fn(T) -> T { ... }

You eliminate closures when doing this. But implementing other functions is no problem.

2

use wrappers

struct F_T_to_T<F: FnOnce(T) -> T>(pub F);

impl<T, F> Foo<T> for F_T_to_T<F> { ... }

which has the downside of needing a wrapper for every new type of function you want.


#3

I think for my case wrappers are the guys that nail the job, as the number of new type of functions will be low, anyways thank you so much >w<


#4

UnFortunately you can implement Fn repeatedly for the same type, with the output being an associated type, therefore invalidating your repeated impls. An example of this is my entry for The Squeeze challenge where the unit struct squeeze has four impls of FnOnce! I could have a type with impls like in this playground