KenSmooth
KenSmooth

Reputation: 285

Is it possible to implement operator overloading for apply::Apply?

Is there any way to implement operator overloading for apply::Apply?

In Rust, many of the operators can be overloaded via traits. That is, some operators can be used to accomplish different tasks based on their input arguments. This is possible because operators are syntactic sugar for method calls. For example, the + operator in a + b calls the add method (as in a.add(b)). This add method is part of the Add trait. Hence, the + operator can be used by any implementor of the Add trait.

/// Represents a type which can have functions applied to it (implemented
/// by default for all types).
pub trait Apply<Res> {
    /// Apply a function which takes the parameter by value.
    fn apply<F: FnOnce(Self) -> Res>(self, f: F) -> Res
    where Self: Sized {
        f(self)
    }
}

impl<T: ?Sized, Res> Apply<Res> for T {
    // use default definitions...
}

Crate overload

For instance,

let string = 1 >> (|x| x * 2) >> (|x: i32| x.to_string());

for

let string = 1.apply(|x| x * 2).apply(|x: i32| x.to_string());

Upvotes: 1

Views: 1562

Answers (1)

DreamConspiracy
DreamConspiracy

Reputation: 393

Not really. Operators don't go on traits, they go on types. It does not make sense to ask "what is the implementation of >> for Apply" but it does make sense to ask "what is the implementation of >> for u8." So what you could try to do is to define Apply as you've defined it, and now:

impl<T, Res, F> std::ops::Shr<F> for T
where
    T: Apply<Res>,
    F: FnOnce(T) -> Res
{
    type Output = Res;
    fn shr(self, rhs: F) -> Res {
        rhs(self)
    }
}

This almost works, except that the compiler reports an error, citing

only traits defined in the current crate can be implemented for a type parameter

The reason for this error is that you have no guarantee that another crate has not implemented the same trait for the same type. If another crate defined a

impl<F: FnOnce(MyType) -> String> std::ops::Shr<F> for MyType { ... }

its not clear what should happen, since now the >> operator has been defined twice for the same type. You could write such an impl if you replaced MyType with some specific type that is local to your crate, but of course now the >> thing won't work for all other types.

Upvotes: 2

Related Questions