【问题标题】:Is there a way to let Rust infer the correct type for an associated type?有没有办法让 Rust 为关联类型推断正确的类型?
【发布时间】:2017-04-10 10:01:20
【问题描述】:

我正在尝试创建一个特征,其中包括返回一些内部数据的迭代器的函数,然后可以由不同的结构实现。一个最小的例子如下:

trait WrapperTrait {
    type WrapperIterator: Iterator<Item=u32>;
    fn iter(&self) -> Self::WrapperIterator;
}
struct Wrapper {
    data: Vec<u32>
}
impl WrapperTrait for Wrapper {
    type WrapperIterator = ...;
    fn iter(&self) -> Self::WrapperIterator {
        return self.data.iter().map(|&x| x);
    }
}

但是,WrapperIterator 的类型相当复杂 - 从错误消息(通过类型不匹配创建)我发现它是:

std::iter::Map<std::slice::Iter<'_, u32>, [closure@borrow.rs:45:37: 45:43]>

有没有办法让 Rust 推断出WrapperIterator 的正确类型?

【问题讨论】:

  • Idiomatic Rust 的函数体只是 self.data.iter().map(|&amp;x| x) — 没有 return,没有 ;

标签: rust


【解决方案1】:

有没有办法让 Rust 为 WrapperIterator 派生正确的类型?

没有。事实上,这与 Rust 所做的正好相反。您注释函数参数并返回类型,然后编译器可以根据此推断方法内部的类型。

从方法的主体中推断出顶级类型会导致可怕的错误消息发生在远离导致它们的位置的位置。 Haskell 很难学会这一点,现在提倡所有顶级函数都有明确的类型签名。 Rust 选择永不走这条路。另见this answer;虽然它谈到了生命周期,但许多相同的观点都成立。

您未提出的问题(我如何返回此迭代器)已经有很多重复项:

感谢您要求另一个完全相同的副本。

【讨论】:

  • 链接的“重复”似乎都没有涵盖实现特征的情况。
  • 链接的问题是关于让 rust 推断函数的返回类型,这不是一回事。关于 Haskell 的反应中固执己见的部分在这种情况下也不太合适。实际上 rust 现在正在努力实现原始发布者想要的:github.com/rust-lang/rust/issues/63063
【解决方案2】:

不幸的是,这在 stable rust 中尚无法实现,但有a plan 介绍此功能。如果您想尝试(当前不稳定的)功能,您可以在 rust nightly 上使用#![feature(min_type_alias_impl_trait)] 进行尝试。您必须为您的 trait 添加一个类型参数:

#![feature(min_type_alias_impl_trait)]

trait WrapperTrait<'a> {
    type WrapperIterator: Iterator<Item = u32> + 'a;
    fn iter(&'a self) -> Self::WrapperIterator;
}

struct Wrapper {
    data: Vec<u32>,
}

impl<'a> WrapperTrait<'a> for Wrapper {
    type WrapperIterator = impl Iterator<Item = u32> + 'a;
    fn iter(&'a self) -> Self::WrapperIterator {
        self.data.iter().map(|&x| x)
    }
}

游乐场链接:https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=a9434bcd32ea9c910fd0f9e329d17bd5

要在不向 trait 添加生命周期参数的情况下做到这一点,还需要另一个不稳定的 rust 特性:通用关联类型。

#![feature(min_type_alias_impl_trait)]
#![feature(generic_associated_types)]

trait WrapperTrait {
    type WrapperIterator<'a>: Iterator<Item = u32>;
    fn iter<'a>(&'a self) -> Self::WrapperIterator<'a>;
}

struct Wrapper {
    data: Vec<u32>,
}

impl WrapperTrait for Wrapper {
    type WrapperIterator<'a> = impl Iterator<Item = u32>;
    fn iter<'a>(&'a self) -> Self::WrapperIterator<'a>{
        self.data.iter().map(|&x| x)
    }
}

游乐场:https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=049c875b27a0e9e472d854e6218df267

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    • 2015-03-17
    • 1970-01-01
    相关资源
    最近更新 更多