I'm having a similar problem. I'm a complete newbie to Rust, but have some experience with Haskell, and a lot of experience with C#, Typescript and C++.
I hacked something together, it seems to work, but I hardly understand any of it, I merely am a slave of the Rust compiler that is telling me what to do
I didn't get it working without boxing though... I guess I would have to add a type parameter to the Fun
struct, but so far, I failed doing so.
#![allow(unused)]
#![feature(unboxed_closures, fn_traits)]
use std::ops::Shr;
use std::ops::Fn;
pub struct Fun<T, R> {
f: Box<dyn Fn(T) -> R>,
}
impl<Args, R> FnOnce<(Args,)> for Fun<Args, R> {
type Output = R;
extern "rust-call" fn call_once(self, args: (Args,)) -> R {
self.f.call_once(args)
}
}
impl<Args, R> FnMut<(Args,)> for Fun<Args, R> {
extern "rust-call" fn call_mut(&mut self, args: (Args,)) -> R {
self.f.call_mut(args)
}
}
impl<Args, R> Fn<(Args,)> for Fun<Args, R> {
extern "rust-call" fn call(&self, args: (Args,)) -> R {
self.f.call(args)
}
}
pub fn fun<T, R>(f: impl Fn(T) -> R + 'static) -> Fun<T, R> {
Fun { f: Box::new(f) }
}
impl<T1: 'static, T2: 'static, R: 'static> Shr<Fun<T2, R>> for Fun<T1, T2> {
type Output = Fun<T1, R>;
fn shr(self, rhs: Fun<T2, R>) -> Self::Output {
let f1 = self.f;
let f2 = rhs.f;
let f = move |x: T1| f2(f1(x));
Fun { f: Box::new(f) }
}
}
fn add(increment: i32) -> Fun<i32, i32> {
fun(move |x| x + increment)
}
fn mul(factor: i32) -> Fun<i32, i32> {
fun(move |x| x * factor)
}
fn main() {
let add_mul = add(1) >> mul(5);
let mut base = 10;
let result = add_mul(base);
println!("{}", result);
base = 100;
let result = add_mul(base);
println!("{}", result);
}