【问题标题】:How to restrict generic implementation of a trait in Rust?如何限制 Rust 中特征的通用实现?
【发布时间】:2016-06-02 05:14:43
【问题描述】:

作为学习 Rust 的借口,我正在编写遗传算法的代码,以及稍后的遗传编程。

我为变异操作声明了一个特征:

pub trait Mutator<IndvidualType> {
    fn mutate(&self, individual: &IndvidualType) -> IndvidualType;
}

为每个IndividualType 实现特征很容易,但我想要更通用的特征,每个列表(向量)类型基因组都通用的特征,例如:

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

我希望有一个通用的mutator,它能够改变每个HasVectorGenomeBaseType 实现Rand(以便能够生成新的随机值)。比如:

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

我收到错误the type parameter `B` is not constrained by the impl trait, self type, or predicates,我无法编译。我不知道如何正确表达。

【问题讨论】:

标签: generics rust


【解决方案1】:

我已经提供了这段代码的完整工作版本on the playground(除了我删除了随机部分)。

首先,我从HasVectorGenome 中删除了IndividualType 参数。这只是实现 trait 的类型,并且您对 trait 的定义与此不一致(new_from_vec 返回IndividualTypeget_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

【讨论】:

  • @Shepmaster 嗯,大概吧?它属于用关联类型替换特征类型参数的相同一般模式,并且在第二个链接中出现相同的错误消息,但答案完全不同(如果我进入 why 而不是仅仅给出代码)。
  • 感谢您的宝贵时间,这是完美的答案!
猜你喜欢
  • 1970-01-01
  • 2016-05-29
  • 1970-01-01
  • 2022-12-07
  • 1970-01-01
  • 1970-01-01
  • 2020-08-15
  • 2021-08-20
  • 2022-08-15
相关资源
最近更新 更多