generics - 解决特征实现冲突

标签 generics traits rust

我正在尝试用 Rust 编写一些通用数学函数,但我一直遇到以下错误消息:

error: conflicting implementations for trait SoAndSo

是否可以解决问题?如果是,怎么办?

例如,我正在尝试编写一个通用的点积,它采用两个迭代器,将它们压缩并迭代对以累积产品。我希望这个函数也能够计算复值点积。复数的点积涉及共轭一侧。我的第一个想法是写一个特征 Dot1用于替换 Mul 的二元函数因为它还结合了左侧参数。完整代码如下:

extern crate num;

use num::complex::Complex;
use num::{Float, Num};

trait Dot1<Rhs, Result> {
    fn dot1(&self, rhs: Rhs) -> Result;
}

impl<T: Float> Dot1<T, T> for T {
    // conjugation for reals is a no-op
    fn dot1(&self, rhs: T) -> T {
        *self * rhs
    }
}

impl<T: Num + Clone> Dot1<Complex<T>, Complex<T>> for Complex<T> {
    fn dot1(&self, rhs: Complex<T>) -> Complex<T> {
        self.conj() * rhs
    }
}

fn main() {
    println!("Hello, world!")
}

Complex<T>不是 Float , 两个“generic impls”之间不应有重叠。我没想到会出现任何问题,但每次我尝试为特征提供多个“通用实现”时,编译器都不喜欢它:

error[E0119]: conflicting implementations of trait `Dot1<num::Complex<_>, num::Complex<_>>` for type `num::Complex<_>`:
  --> src/main.rs:17:1
   |
10 | impl<T: Float> Dot1<T, T> for T {
   | ------------------------------- first implementation here
...
17 | impl<T: Num + Clone> Dot1<Complex<T>, Complex<T>> for Complex<T> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `num::Complex<_>`
   |
   = note: upstream crates may add new impl of trait `num::Float` for type `num::Complex<_>` in future versions

如何编写适用于实数和复数的基于迭代器的通用点积?使用迭代器、压缩它们等等都不是问题,我什至能够弄清楚哪些类型参数与哪些边界一起使用。我似乎无法使用上述特征“统一”某些数据类型。

最佳答案

这里的问题是(当前)编译器没有注册 Complex<T>不执行 Float .想象一下如果 Complex没有实现Float : 要么必须有某种方法来决定哪个 impl使用,否则必须取缔重叠代码......但是如果有人只添加 impl<T> Float for Complex<T> 怎么办?在编译器不知道的其他一些 crate 中?

这最后一点很关键:与 Haskell 不同,Rust 的设计允许这段代码完美无误,没有任何风险,这都是因为 Rust 在处理最后一点的方式上有所不同。如果您在可以看到类型 Type 的 crate 中和一个特征 Trait ,那么您可以 100% 确定是否 Type工具 Trait : Rust 没有 Haskell 的开放世界假设,因为你只能写 impl Trait for Type如果TraitType位于当前 crate (编译单元)中,也就是说,你不能有 orphan instances ,有人实现 Float对于 Complex<T>在某个遥远的箱子里。

RFC 24(Chris 链接到)recognises this ,允许这些通用实现与更具体的实现共存,只要保证实现不重叠即可。

关于generics - 解决特征实现冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24554738/

相关文章:

memory - 'static: std::marker::Sized` 不满足 - 我需要 Box 吗?

vector - 在 Rust 中初始化向量的向量

file-io - 打开文件返回ErrorKind::Other 'Error: Os, code: 20, message: “Not a directory”'

.net - 包含事件的通用集合和字典类

java - 如何在java中处理通用列表List<MyClass>以特定方式获取结果集

rust - 为什么在取消引用的特征对象或切片上调用方法会编译?

function - 如何从泛型函数返回具体类型?

generics - 在 clojure 中为泛型类提供类型提示

c# - 泛型与 IBindingList 和 BindingList<T> 混淆

error-handling - Rust Arc/Mutex Try 宏借用的内容