如何限制在Rust中的特征的通用实现? [英] How to restrict generic implementation of a trait in Rust?

查看:95
本文介绍了如何限制在Rust中的特征的通用实现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

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

对于每一个 IndividualType ,但我想要一些更一般的东西,这是每个列表(矢量)类型基因组常见的特征,如:

  pub trait HasVectorGenome< IndividualType,BaseType> {
fn new_from_vec(基因组:Vec< BaseType>) - > IndvidualType;
fn get_vec(& self) - > VEC<碱基类型取代;
}

我想要一个通用的mutator,它能够将每个 HasVectorGenome 其中 BaseType implements Rand (为了能够生成新的随机值)。例如:

  struct GeneralMutator; 

impl< B,T>增变< T> for GeneralMutator
其中T:HasVectorGenome< T,B>,
B:Rand
{
fn mutate(& self,individual:& T) - > T {
let基因组:Vec< B> = individual.get_vec();
基因组[0] = rand :: random ::< B>();
T :: new_from_vec(genome)
}
}

我得到错误类型参数`B`不受impl特征,自我类型或谓词的限制,我无法编译。我不知道如何正确表达这一点。

解决方案

我已经把这段代码的完整工作版本上的https://play.rust-lang.org/?gist=9d66c3969ed377dd9314&version=stablerel =nofollow>(除了我将随机部分剔除)。



首先,我从 HasVectorGenome 中删除​​了 IndividualType 参数。这只是实现特征的类型,而你对特征的定义与此不一致( new_from_vec 返回 IndividualType 但是 get_vec 消费 Self )。



第二,我做了 BaseType 一个关联类型,这意味着任何单个类型都有一个唯一的唯一基类型。这在技术上是一种限制,但在大多数情况下,您不需要灵活性,并且使类型更简单(实际上是摆脱错误所需的主要更改)。所以这个特性现在是:

  pub trait HasVectorGenome {
type BaseType;
fn new_from_vec(基因组:Vec< Self :: BaseType>) - >自;
fn get_vec(& self) - > VEC<自::碱基类型取代;
}

然后,我调整了 GeneralMutator的where子句执行:

  impl< T>增变< T> for GeneralMutator 
其中T:HasVectorGenome,
T :: BaseType:Rand


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

这篇关于如何限制在Rust中的特征的通用实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆