1
votes

I encountered an issue where I have this trait (some things omitted):

use rand::Rng;
pub trait GeneticAlgorithm<R, Ins, C> : Clone where R: Rng {
    fn call<F>(&self, program: F) where F: FnOnce(&C);
}

This struct implements the trait:

pub struct Mep<Ins> {
    instructions: Vec<Ins>,
    unit_mutate_size: usize,
    crossover_points: usize,
}

impl<R, Ins> GeneticAlgorithm<R, Ins, Vec<Ins>> for Mep<Ins> where R: Rng, Ins: Clone {
    fn call<F>(&self, program: F) where F: FnOnce(&Vec<Ins>) {
        program(&self.instructions);
    }
}

In a test I attempt to run this:

let mut rng = Isaac64Rng::from_seed(&[1, 2, 3, 4]);
let (a, b) = {
    let mut clos = || Mep::new(3, 3, rng.gen_iter::<u32>().map(|x| x % 10).take(10));
    (clos(), clos())
};
let mut c = Mep::mate((&a, &b), &mut rng);
c.call(|x: &Vec<u32>| panic!());

Rust claims that it cannot infer a type somewhere, but I am not sure how to specify the type of a closure if that is the issue, nor am I able to identify which specific generic parameter is causing the issue:

error: unable to infer enough type information about `_`; type annotations or generic parameter binding required [E0282]
c.call(|x: &Vec<u32>| panic!());

Which generic parameter is necessary to specify?

If anyone would like to build the code itself, I am hosting it on GitHub.

1

1 Answers

3
votes

Let's look at your declaration, trimmed a bit for clarity:

pub trait GeneticAlgorithm<R, Ins, C> {
    fn call<F>(&self, program: F);
}

There are 4 generic types here: R, Ins, C, and F. Now, let's look at your implementation (again, trimmed):

impl<R, Ins> GeneticAlgorithm<R, Ins, Vec<Ins>> for Mep<Ins> {
    fn call<F>(&self, program: F);
}

So, you have now provided a concrete value to C that depends on Ins. You still have 3 parameters that the user has to specify: Ins, F, and R.

F will be specified when the function is called, based on the closure type. Ins will be specified when the Mep structure is created.

That leaves R. Based on these declarations, what is R supposed to be? It's impossible to tell. This appears to just be an error in your implementation; it's likely that you should have it somewhere. The other option is that you simply have a parameter that you don't need.