1

Composition operator and pipe forward operator in Rust

use std::ops::Shr;

struct Wrapped<T>(T);

impl<A, B, F> Shr<F> for Wrapped<A>
where
    F: FnOnce(A) -> B,
{
    type Output = Wrapped<B>;

    fn shr(self, f: F) -> Wrapped<B> {
        Wrapped(f(self.0))
    }
}

fn main() {
    let string = Wrapped(1) >> (|x| x + 1) >> (|x| 2 * x) >> (|x: i32| x.to_string());
    println!("{}", string.0);
}
// prints `4`

Here's a code of pipeline operator for struct: Wrapped by overloading an operator, but I need one that can be used for native values that I think as &dyn Any.

Since I don't understand type system of Rust yet, so I did like

use std::any::Any;

impl<A, B, F: Fn(A) -> B> Shr<F> for &dyn Any {
    type Output = &dyn Any;

    fn shr(self, f: F) -> &dyn Any {
        f(self.0)
    }
}

but with obvious errors.

How can I sort this out? Thanks.

SmoothTraderKen
  • 602
  • 4
  • 16
  • Does [How do I implement a trait I don't own for a type I don't own?](https://stackoverflow.com/questions/25413201/how-do-i-implement-a-trait-i-dont-own-for-a-type-i-dont-own) answer your question? – mcarton Sep 06 '20 at 19:04
  • @mcarton Yeah, I mean no, it does not help... do you suggest it is impossible to implement overloading operator on any? Thanks. – SmoothTraderKen Sep 06 '20 at 19:23
  • 1
    Yes, it's impossible. – mcarton Sep 06 '20 at 19:28
  • 1
    Moreover, the usual way to implement a trait for any type is `impl Trait for T`, not using `Any`. – mcarton Sep 06 '20 at 19:29
  • Ok, thank you, I understand. I wonder if there's a workaround, or hopefully this custom operator possible like Haskell. – SmoothTraderKen Sep 06 '20 at 19:35
  • Using an operator: No. That's a feature of the language; There is no workaround. Using a custom trait: [Yes](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=078e1cee4dd5349af81361fed20e5c5f). – mcarton Sep 06 '20 at 20:05
  • @mcarton Thanks a lot. This looks good and should be shared, why don't you answer this? I will accept as a solution with my appreciation. – SmoothTraderKen Sep 06 '20 at 22:34

1 Answers1

2

Thanks to @mcarton,

Rust pipeline operator for Any by overloading operators

I found a similar solution:

https://docs.rs/apply/0.3.0/apply/trait.Apply.html

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)
    }

    /// Apply a function which takes the parameter by reference.
    fn apply_ref<F: FnOnce(&Self) -> Res>(&self, f: F) -> Res {
        f(self)
    }

    /// Apply a function which takes the parameter by mutable reference.
    fn apply_mut<F: FnOnce(&mut Self) -> Res>(&mut self, f: F) -> Res {
        f(self)
    }
}

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

fn main() {
    let string = 1
        .apply(|x| x * 2)
        .apply(|x| x + 1)
        .apply(|x: i32| x.to_string());
    println!("{}", string);
}
SmoothTraderKen
  • 602
  • 4
  • 16