如何在Rust中限制trait的通用实现?

5
作为学习 Rust 的借口,我正在编写遗传算法的代码,之后会编写遗传编程的代码。
我声明了一个用于变异操作的 trait:
pub trait Mutator<IndvidualType> {
    fn mutate(&self, individual: &IndvidualType) -> IndvidualType;
}

对于每个IndividualType来说,实现trait非常容易,但我想要更通用的trait,适用于每个列表(向量)类型的基因组,比如:

pub trait HasVectorGenome<IndividualType, BaseType>  {
    fn new_from_vec(genome: Vec<BaseType>) -> IndvidualType;
    fn get_vec(&self) -> Vec<BaseType>;
}

我希望有一个通用的变异器,可以变异每一个实现了Rand接口的HasVectorGenomeBaseType(以便能够生成新的随机值)。类似于:

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)
    }
}

我遇到了错误 类型参数`B`没有通过实现特质、自身类型或谓词进行限制,导致编译失败。我不知道该如何正确表达这个问题。


可能是 https://dev59.com/cV0a5IYBdhLWcg3wW3ca 或 https://dev59.com/mo3da4cB1Zd3GeqP37pk 的重复问题。 - Shepmaster
1个回答

4

我已经在playground上放了一个完整可工作的代码版本(除了随机部分被stub掉了):链接在此

首先,我从HasVectorGenome中移除了IndividualType参数。这只是实现该特性的类型,而您对该特性的定义在这方面不一致(new_from_vec返回IndividualType,但get_vec消耗Self)。

其次,我将BaseType设置为关联类型,这意味着任何个体类型都有一个单一的基础类型。这在技术上是一种限制,但在大多数情况下,您不需要这种灵活性,它使类型更简单(实际上这是需要进行的主要更改以消除您看到的错误)。因此,该特性现在如下:

pub trait HasVectorGenome  {
    type BaseType;
    fn new_from_vec(genome: Vec<Self::BaseType>) -> Self;
    fn get_vec(&self) -> Vec<Self::BaseType>;
}

然后,我调整了GeneralMutator实现的where子句:

impl<T> Mutator<T> for GeneralMutator
  where T: HasVectorGenome,
        T::BaseType : Rand

你认为这个问题是 https://dev59.com/cV0a5IYBdhLWcg3wW3ca 还是 https://dev59.com/mo3da4cB1Zd3GeqP37pk 的重复吗? - Shepmaster
@Shepmaster 嗯,有点像,也许吧?它遵循将特质类型参数替换为关联类型的相同一般模式,并且在第二个链接中出现了相同的错误消息,但答案是非常不同的(如果我深入解释为什么而不仅仅是给出代码,那么答案仍然会不同)。 - user395760
谢谢您的时间,这是完美的答案! - KilyenOrs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接