"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?
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
}