Lifting binary operations, e.g. T+T → Option<T> + Option<T>

I was contemplating suggesting impl<T:Add<U>,U> Add<Option<U>> for Option<T>, but unfortunately (IMHO) the fact that Option was made Ord prevents that from being done consistently for the comparison operators, so I don't know if it's a good idea for the other operators.

Looks like nightly can apparently already make a lifting adapter:

#![feature(unboxed_closures)]
#![feature(fn_traits)]

fn main() {
    let f = OptionLift(std::ops::Add::add);
    assert_eq!(f(Some(2), Some(3)), Some(5));
    
    let g = OptionLift(std::ops::Neg::neg);
    assert_eq!(g(Some(2)), Some(-2));
}

struct OptionLift<F>(F);

impl<F:FnOnce<(T0,)>,T0> FnOnce<(Option<T0>,)> for OptionLift<F> {
    type Output = Option<F::Output>;
    extern "rust-call" fn call_once(self, (a0,): (Option<T0>,)) -> Self::Output {
        Some((self.0)(a0?))
    }
}

impl<F:FnOnce<(T0,T1,)>,T0,T1> FnOnce<(Option<T0>,Option<T1>,)> for OptionLift<F> {
    type Output = Option<F::Output>;
    extern "rust-call" fn call_once(self, (a0,a1,): (Option<T0>,Option<T1>,)) -> Self::Output {
        Some((self.0)(a0?,a1?))
    }
}
2 Likes