繁体   English   中英

Rust 无法推断通用特征 impl 的返回类型

[英]Rust unable to infer return type for generic trait impl

我又一次玩得很开心,试图满足 Rust 中的类型检查器。 这是我对即将出现的代码示例的模糊看法。 我有一个特征,它的方法需要一些 arguments,为了具有灵活性,我希望能够以任何可能的组合将参数设为特定类型,只要传入类型的关联类型实现给定的特征.

注意 trait 的类型参数AB表示函数的输入。 现在我有一个版本,其中这些参数是函数的通用参数,但这不起作用,因为此 trait 的其他实现依赖于知道它需要哪些输入,因此它们必须是 trait generic 的一部分,并且它们不能移动下到泛型函数。

这是特征的样子:

pub trait Filter<T: Scalar + Lapack, A: Data<Elem=T>, B: Data<Elem=T>> {
    type Prediction;
    type Update;
    fn predict(&self, states: &ArrayBase<A, Ix2>, covariances: &ArrayBase<B, Ix3>) -> Self::Prediction;
    fn update(&self, states: &ArrayBase<A, Ix2>, covariances: &ArrayBase<A, Ix3>, measurements: &ArrayBase<A, Ix2>) -> Self::Update;
}

然后我有一个结构,它实现了这个特征,并且也不关心为特征方法提供哪些输入,只要它们的关联类型实现给定的特征,所以这是结构和 impl 的样子:

pub struct KalmanFilter<T: Scalar + Lapack> {
    transition_matrix: Array2<T>,
    observation_matrix: Array2<T>,
    transition_covariance: Array2<T>,
    observation_covariance: Array2<T>,
}

impl<T: Scalar + Lapack, A: Data<Elem=T>, B: Data<Elem=T>> Filter<T, A, B> for KalmanFilter<T> {

    type Prediction = (ArrayBase<OwnedRepr<T>, Ix2>, ArrayBase<OwnedRepr<T>, Ix3>);
    type Update = (ArrayBase<OwnedRepr<T>, Ix3>, ArrayBase<OwnedRepr<T>, Ix3>);

    fn predict(&self, states: &ArrayBase<A, Ix2>, covariances: &ArrayBase<B, Ix3>) -> Self::Prediction {
        ......... code ..... code
    }

    fn update(
        &self,
        states: &ArrayBase<A, Ix2>,
        covariances: &ArrayBase<A, Ix3>,
        measurements: &ArrayBase<A, Ix2>,
    ) -> Self::Update {
        ......... code ..... code
}

现在我们来看看错误信息。 即当我尝试从上面的结构中调用更新方法时,我得到:

error[E0284]: type annotations needed: cannot satisfy `<_ as RawData>::Elem == f64`
   --> src/filter/kalman.rs:320:20
    |
320 |         let a = kf.update(&states, &covariances, &measurements);
    |                    ^^^^^^ cannot satisfy `<_ as RawData>::Elem == f64`
    |
    = note: required because of the requirements on the impl of `filter_traits::Filter<f64, OwnedRepr<f64>, _>` for `kalman::KalmanFilter<f64>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0284`.
error: could not compile `rusty_rudolf`

现在这很有趣,因为如果我手动进行单模化,并且基本上在 impl 块中,我将类型参数T替换为f64它就可以工作。 为什么这不起作用,为什么它适用于手动单态化?

编辑:还有一件事,如果我放弃将类型组合作为输入的能力,并且如果我在上面的特征中删除类型参数B ,它就会起作用。 不知何故,第二个类型参数的引入会导致问题。

问题可能出在第二个 function update()上,它无法推断B的类型,因为它没有引用 function 签名中的B类型。 查看predict的签名,您可能希望在update function 中使用B类型作为covariances

fn update(
        &self,
        states: &ArrayBase<A, Ix2>,
        covariances: &ArrayBase<B, Ix3>, // use B instead of A
        measurements: &ArrayBase<A, Ix2>,
    ) -> Self::Update {
...    
}

编辑:还有一件事,如果我放弃将类型组合作为输入的能力,并且如果我在上面的特征中删除类型参数 B,它就会起作用。 不知何故,第二个类型参数的引入会导致问题。

想象一下,您有两个具有相同TA以及不同B的 trait 实现。 编译器如何知道使用哪一个?

最后,go 如何解决这个问题? 有没有办法说类型参数是完全独立的,或者至少说关联类型只依赖于第一个类型参数?

将您的特质分为 2 似乎是合理的:

pub trait FilterUpdate<T: Scalar + Lapack, A: Data<Elem=T>> {
    type Update;
    fn update(&self, states: &ArrayBase<A, Ix2>, covariances: &ArrayBase<A, Ix3>, measurements: &ArrayBase<A, Ix2>) -> Self::Update;
}

pub trait Filter<T: Scalar + Lapack, A: Data<Elem=T>, B: Data<Elem=T>> : FilterUpdate<T, A> {
    type Prediction;
    fn predict(&self, states: &ArrayBase<A, Ix2>, covariances: &ArrayBase<B, Ix3>) -> Self::Prediction;
}

那么对于特定A ,您只能有一个update实现。 或者可能首先使B成为关联类型,而不是特征的类型参数。

或者您可以保留当前的 API 并明确指定特征类型参数。 根据错误消息,我猜它看起来像这样:

let a = <KalmanFilter<f64> as Filter<f64, OwnedRepr<f64>, ???>>::update(&kf, &states, &covariances, &measurements)

你需要在哪里决定什么??? 是。

  1. 我猜你最终需要为大多数update调用这样做。

  2. 助手 function 可以简化调用,特别是如果我正确理解B是什么通常无关紧要并且您可以将其等同于A

     fn update<T: Scalar + Lapack, A: Data<Elem=T>, F: Filter<T, A, A>>(filter: &F, states: &ArrayBase<A, Ix2>, covariances: &ArrayBase<A, Ix3>, measurements: &ArrayBase<A, Ix2>) -> F::Update { filter.update(states, covariances, measurements) }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM