Option...">

"Ambiguous associated type" when returning a common lambda

I have this code (invented and purely experimental)

fn math_op(op: &str) -> Option<Box<Fn(i32, i32) -> i32>> {
    let ret: Option<Box<Fn(i32, i32) -> i32>> = match op {
        "+" => Some(Box::new(|a: i32, b: i32| -> i32 { a + b } )),
        "-" => Some(Box::new(|a: i32, b: i32| -> i32 { a - b } )),
        "*" => Some(Box::new(|a: i32, b: i32| -> i32 { a * b } )),
        "/" => Some(Box::new(|a: i32, b: i32| -> i32 { a / b } )),
        _ => None,
    };

    ret
}

It returns a function / lambda that takes two operands and returns the result (in this case, the operations of addition, subtraction, division and multiplication)

What can be called like this:

let add: Option<Box<Fn(i32, i32) -> i32>> = math_op("+");
println!("Add {}", add.unwrap()(10, 2));

I really would like to make a general version of this, as long as I have ...

fn math_op_gen<T>(op: &str) -> Option<Box<Fn(T, T) -> T::Output>> 
    where T: std::ops::Add + std::ops::Sub + std::ops::Mul + std::ops::Div {
        let ret: Option<Box<Fn(T, T) -> T::Output>> = match op {
            "+" => Some(Box::new(|a, b| { a + b } )),
            "-" => Some(Box::new(|a, b| { a - b } )),
            "*" => Some(Box::new(|a, b| { a * b } )),
            "/" => Some(Box::new(|a, b| { a / b } )),
            _ => None,
        };

        ret
}

But when I create, I get the following errors:

error: ambiguous associated type `Output` in bounds of `T` [E0221]
note: associated type `T` could derive from `core::ops::Div`
note: associated type `T` could derive from `core::ops::Mul`
note: associated type `T` could derive from `core::ops::Sub`
note: associated type `T` could derive from `core::ops::Add`

I understand this is due to the fact that the compiler cannot determine which type of T :: Output is the result of various properties that I implemented. Is there any other way to write this to make it work?

+4
source share
1 answer

Add, Sub, Mul Div. , Output .

fn math_op_gen<T, R>(op: &str) -> Option<Box<Fn(T, T) -> R>> 
    where T: std::ops::Add<Output=R> +
             std::ops::Sub<Output=R> +
             std::ops::Mul<Output=R> +
             std::ops::Div<Output=R> {
        let ret: Option<Box<Fn(T, T) -> R>> = match op {
            "+" => Some(Box::new(|a, b| { a + b } )),
            "-" => Some(Box::new(|a, b| { a - b } )),
            "*" => Some(Box::new(|a, b| { a * b } )),
            "/" => Some(Box::new(|a, b| { a / b } )),
            _ => None,
        };

        ret
}
+4

Source: https://habr.com/ru/post/1612095/


All Articles