As an excuse to learn Rust, I'm working on code for genetic algorithms, and genetic programming later.
I declared a trait for mutation operations:
pub trait Mutator<IndvidualType> {
fn mutate(&self, individual: &IndvidualType) -> IndvidualType;
}
It is easy to implement the trait for every single IndividualType
, but I want something more general, a trait which is common for every list (vector) type genome, something like:
pub trait HasVectorGenome<IndividualType, BaseType> {
fn new_from_vec(genome: Vec<BaseType>) -> IndvidualType;
fn get_vec(&self) -> Vec<BaseType>;
}
I want to have a generic mutator which is able to mutate every HasVectorGenome
whose BaseType
implements Rand
(in order to be able to generate a new random value). Something like:
struct GeneralMutator;
impl<B, T> Mutator<T> for GeneralMutator
where T: HasVectorGenome<T, B>,
B: Rand
{
fn mutate(&self, individual: &T) -> T {
let genome: Vec<B> = individual.get_vec();
genome[0] = rand::random::<B>();
T::new_from_vec(genome)
}
}
I've got the error the type parameter `B` is not constrained by the impl trait, self type, or predicates
, and I can't compile. I do not know how to express this correctly.
I've put a complete working version of this code on the playground (except that I stubbed out the random parts).
First, I removed the
IndividualType
parameter fromHasVectorGenome
. This is simply the type for which the trait is implemented, and your definition of the trait is inconsistent about this (new_from_vec
returnsIndividualType
butget_vec
consumesSelf
).Second, I made
BaseType
an associated type, meaning that there is a single unique base type for any individual type. This is technically a restriction, but in most circumstances you don't need the flexibility and it makes the types simpler (and is in fact the primary change needed to get rid of the error you're seeing). So the trait is now:Then, I adjusted the where clause of the
GeneralMutator
implementation: