2015-06-15 4 views
2

Фон: я использую библиотеку 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`

Я не верю в это должна быть ошибка s ince Я определяю реализацию для структуры, которую я определил в этом модуле. Как мне это исправить?

+0

ли 'SquareMat' обеспечить тип для' n', 'V', так что вы можете сделать что-то вроде:' паба STRUCT Multivar > { μ: M :: V, Σ: M, Маркер: PhantomData } ' – Jarod42

+2

, пожалуйста, предоставьте [минимальный компилируемый и проверяемый пример] (http://stackoverflow.com/help/mcve), а главное, в вашем коде отсутствует символ SquareMat, а ваши сообщения об ошибках ссылаются на' MyStruct', который не показан нигде.Для Rust-questions это наиболее удобно для ответчиков, если ваша ошибка воспроизводится в Playpen на [play.rust-lang.org] (http://play.rust-lang.org) –

+0

. Также рассмотрите существующие вопросы для обе ошибки ([1] (http://stackoverflow.com/search?q=%5Brust%5D+only+traits+defined+in+the+current+crate+can+be+implemented+for+a+type+ параметр), [2] (http://stackoverflow.com/search?q=%5Brust%5D+conflicting+implementations+for+trait)) и ** объясните нам **, почему ваш вопрос отличается. В противном случае вы можете просто быть отмечены как дубликаты, закрыты или получить бесполезный ответ. – Shepmaster

ответ

4

Проблема с вашим кодом заключается в том, что в нем есть нарушение согласованности, и, по всей вероятности, любые попытки исправить это приведут к новым нарушениям согласованности.

Правила когерентности в Rust несколько сложны, однако они основаны на одном принципе: вы можете реализовать «свои» черты для произвольных типов, и вы можете реализовать произвольные черты для «ваших» типов. Это звучит просто, но становится сложным, когда параметры типа попадают в картину - оказывается, что существует несколько способов определить, какие типы являются «вашими», а какие нет.

В данном случае ошибка в том, что вы реализуете внешнюю черту для параметра типа непосредственно:

impl<N, V, M> Mul<Multivar<N, V, M>> for M 

Это является прямым нарушением вышеуказанного принципа - вы не можете реализовать черты вы не для типов, которыми вы не владеете (такие реализации называются «сиротами»). Это именно то, о чем ваша первая ошибка.

Вторая ошибка заставляет меня думать, что у вас есть более Mul реализаций, чем вы предоставили здесь; во всяком случае, это также нарушение когерентности. Обычно такая ошибка возникает, когда у вас есть пересечения множеств типов, применяемых для двух или более различных реализаций признака:

use std::fmt; 

trait X {} 

impl X for i32 {} 
impl<T: fmt::Display> X for T {} 

Вот варианты реализации конфликтующие потому что они оба применимы для i32i32, поскольку реализует fmt::Display.

На самом деле, трудно сказать, чего вы хотите, поэтому также трудно дать удовлетворительный ответ. Я попытался объяснить причину этих ошибок выше, надеюсь, это поможет вам правильно написать реализации признаков. Если вам интересно, вы можете найти больше в блоге this о правилах для сирот.

Смежные вопросы