sel*_*tze 5 generics traits rust
我正在尝试在Rust中编写一些通用的数学函数,并且我一直遇到以下错误消息:
error: conflicting implementations for trait SoAndSo
Run Code Online (Sandbox Code Playgroud)
有可能解决问题吗?如果是这样,怎么样?
例如,我正在尝试编写一个带有两个迭代器的通用点积,拉链它们并迭代它们以积累产品.我希望这个功能也能够计算复值点产品.复数上的点积包括共轭一侧.我的第一个想法是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!")
}
Run Code Online (Sandbox Code Playgroud)
由于a Complex<T>不是Float,因此两个"通用impls"之间应该没有重叠.我没想到会有任何问题,但每当我尝试为特征提供多个"通用impl"时,编译器都不喜欢它:
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
Run Code Online (Sandbox Code Playgroud)
如何编写适用于实数和复数的通用,基于迭代器的点积?取迭代器,压缩它们等不是问题,我甚至能够找出使用哪个类型参数与哪个边界.我似乎无法使用上面的特征"统一"某些数据类型.
这里的问题是(当前)编译器没有注册Complex<T>未实现的Float. 想象一下,如果Complex确实实现了Float:要么必须有某种方法来决定impl使用哪个,要么必须取缔重叠的代码......但是如果有人只将impl<T> Float for Complex<T>编译器不知道的其他板条箱添加呢?
最后一点是关键:与 Haskell 不同,Rust 的设计允许这段代码完全OK,没有任何风险,这都是因为 Rust 处理最后一点的方式有所不同。如果你在一个可以看到类型Type和特征的板条箱中Trait,那么你100%确定是否Type实现了Trait:Rust没有Haskell的开放世界假设,因为你只能编写impl Trait for TypeifTrait或者Type位于当前板条箱中(编译单位),也就是说,你不能有孤儿实例,有人在某个遥远的箱子中实现Float了Complex<T>。
RFC 24(Chris 链接到的)认识到这一点,允许这些通用实现与更具体的实现共存,只要保证实现不重叠即可。
| 归档时间: |
|
| 查看次数: |
2433 次 |
| 最近记录: |