背景:我正在使用nalgebra
库,我想创建一个代表多元正态分布的结构。 M
是矩阵的类型,例如Mat4<f64>
。
我目前的尝试是这样的:
use std::ops::Mul;
use std::marker::PhantomData;
use nalgebra::*;
#[allow(non_snake_case)]
pub struct Multivar<N, V, M: SquareMat<N, V>> {
μ: V,
Σ: M,
marker: PhantomData<N>
}
impl<N, V, M> Mul<Multivar<N, V, M>> for M {
type Output = Multivar<N, V, M>;
fn mul(self, rhs: Multivar<N, V, M>) -> Multivar<N, V, M> {
Multivar {
μ: self * rhs.μ,
Σ: self * rhs.Σ * transpose(&self)
}
}
}
然而,编译器抱怨:
error: type parameter `M` must be used as the type parameter for some local type (e.g. `MyStruct<T>`); only traits defined in the current crate can be implemented for a type parameter
和
error: conflicting implementations for trait `core::ops::Mul`
我不相信这应该是一个错误,因为我定义了我在此模块中定义的结构的实现。我该如何解决这个问题?
答案 0 :(得分:4)
您的代码存在的问题是,您的代码存在连贯性违规行为,并且很有可能,任何修复代码的行为都会导致新的一致性违规行为。
Rust中的一致性规则有点复杂,但是,它们基于一个原则:您可以实现&#34;您的&#34;任意类型的特征,你可以为&#34;你的&#34;实现任意特征。类型。这听起来很简单,但是当类型参数出现时会变得复杂 - 事实证明,有多种方法可以定义哪些类型是&#34;你的&#34;哪些不是。
在这种特殊情况下,错误在于您直接为类型参数实现外部特征:
impl<N, V, M> Mul<Multivar<N, V, M>> for M
这直接违反了上述原则 - 您无法实现您不拥有的类型所拥有的特征(此类实现称为&#34;孤儿impls&#34;)。这正是您的第一个错误。
第二个错误让我觉得你有比你在这里提供的更多Mul
个实现;无论如何,这也是一致性违规。通常,如果您具有适用于特征的两个或更多不同实现的类型集的交集,则会导致此类错误:
use std::fmt;
trait X {}
impl X for i32 {}
impl<T: fmt::Display> X for T {}
此处的实施具有冲突性,因为它们都适用于i32
,因为i32
实施fmt::Display
。
事实上,很难说出你想要的东西,所以很难给出令人满意的答案。我试图解释上面这些错误的原因,希望它能帮助你正确编写特征实现。如果您有兴趣,可以在this关于孤儿规则的博文中找到更多信息。