If I wanted to generate a polynomial function in Rust, one way to do it is the following,
fn new_polynomial(vec: Vec<i32>) -> impl Fn(i32) -> i32 {
move |x| vec.iter().fold(0, |acc, a| x * acc + a)
}
But, since I want to define lots of higher-order functions (find roots, differentiate, integrate, etc.), I would like to have these functions implemented as methods. The code that I have is as follows,
trait Function {
fn new_polynomial(vec: Vec<i32>) -> Self;
fn eval(&self, x: i32) -> i32;
}
impl<F> Function for F
where
F: Fn(i32) -> i32,
{
fn new_polynomial(vec: Vec<i32>) -> Self {
move |x| vec.iter().fold(0, |acc, a| x * acc + a)
}
fn eval(&self, x: i32) -> i32 {
self(x)
}
}
and produces the following E308,
error[E0308]: mismatched types
--> src/main.rs:14:9
|
9 | impl<F> Function for F
| - expected this type parameter
...
13 | fn new_polynomial(vec: Vec<i32>) -> Self {
| ---- expected `F` because of return type
14 | move |x| vec.iter().fold(0, |acc, a| x * acc + a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `F`, found closure
|
= note: expected type parameter `F`
found closure `{closure@src/main.rs:14:9: 14:17}`
= help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `F`
Hopefully I'm not missing something obvious here.
Thanks.
If you want a method on vectors that converts them to a polynomial, you should implement the trait on the vectors, not on the functions:
trait ToPolynomial {
fn new_polynomial(self) -> impl Fn(i32) -> i32;
}
impl ToPolynomial for Vec<i32> {
fn new_polynomial(self) -> impl Fn(i32) -> i32 {
move |x| self.iter().fold(0, |acc, a| x * acc + a)
}
}
The Function
trait should not contain this method:
trait Function {
fn eval(&self, x: i32) -> i32;
}
impl<F> Function for F
where
F: Fn(i32) -> i32,
{
fn eval(&self, x: i32) -> i32 {
self(x)
}
}
You would use these traits like this:
let polynomial = vec![1,2,3].new_polynomial();
println!("{}", polynomial.eval(2));