Reputation: 1496
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.
Upvotes: 5
Views: 4429
Reputation:
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 from HasVectorGenome
. This is simply the type for which the trait is implemented, and your definition of the trait is inconsistent about this (new_from_vec
returns IndividualType
but get_vec
consumes Self
).
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:
pub trait HasVectorGenome {
type BaseType;
fn new_from_vec(genome: Vec<Self::BaseType>) -> Self;
fn get_vec(&self) -> Vec<Self::BaseType>;
}
Then, I adjusted the where clause of the GeneralMutator
implementation:
impl<T> Mutator<T> for GeneralMutator
where T: HasVectorGenome,
T::BaseType : Rand
Upvotes: 4