【问题标题】:How can I explicitly say what an associated type should be?我怎样才能明确地说关联类型应该是什么?
【发布时间】:2021-06-18 10:56:36
【问题描述】:

我有一个类似于Iterator 的特征,以及围绕它的包装器:

pub struct Wrapped<I: Iterator>(I);

包装迭代器上的许多函数使用 impl-trait 返回新的包装迭代器。

impl <I: Iterator> Wrapped<I> {
  pub fn foo(self) -> Wrapped<impl Iterator<Item=Foo<I::Item>>> {...}
  pub fn bar(self) -> Wrapped<impl Iterator<Item=Bar<I::Item>>> {...}
}

这样一段时间后,用户就很容易忘记调用代码中迭代器项是什么(例如,对于像my_wrapped.foo().bar().bar().foo() 这样的表达式)。

我想给用户一种方法来明确指定他们期望Item 是什么类型,如果不是那种类型,那么就会出现编译时错误:

let y = x.foo().bar().bar().foo().assert_item_type::<Foo<Bar<Bar<Foo<X>>>>>()

但到目前为止,我发现这样做的唯一方法有点奇怪和丑陋。有没有更清洁的方法?

pub trait Is {
    type Myself;
}

impl<T> Is for T {
    type Myself = T;
}

impl <I: Iterator> Wrapped<I> {
    pub fn assert_item_type<Item: Is<Myself = I::Item>>(self) -> Self {
        self
    }
}

【问题讨论】:

  • 我想说的是,除了在Wrapped 上使用通用扩展特征而不是固有 impl 之外,您的方法尽可能干净。你不能在关联类型之外使用=(我相信现在),所以Is trait 是必要的。

标签: rust type-hinting associated-types


【解决方案1】:

如果您不介意使用独立函数,您可以采用类似的方法而不需要任何特征:

fn assert_item_type<I: Iterator<Item=T>, T>(x: Wrapped<I>) -> Wrapped<I> {
    x
}


let y = assert_item_type::<_, Foo<Bar<Bar<Foo<X>>>>>(x.foo().bar().bar().foo());

不幸的是,currently not possibleassert_item_type 中的 I 类型参数替换为 impl Iterator(这将去掉 turbofish 中的下划线),因为编译器 does not allow us 在以下情况下提供显式泛型参数impl Trait 用于参数位置。

如果在编译器中引入此功能,则该函数可以(假设地)定义并用作:

fn assert_item_type<T>(x: Wrapped<impl Iterator<Item=T>>) -> Wrapped<impl Iterator<Item=T>> {
    x
}


let y = assert_item_type::<Foo<Bar<Bar<Foo<X>>>>>(x.foo().bar().bar().foo());

Playground

【讨论】:

    【解决方案2】:

    这似乎不是 API 的目标。相反,用户不能在自己的代码中依赖典型的 impl trait 语法来完成这项任务吗?

    例如

    struct X;
    
    fn accept_iterator(it: impl Iterator<Item = X>) { ... }
    
    fn main() {
        let complex_iterator = x.foo().bar().foo().bar()...;
        // Will only compile if `complex_iterator` is an iterator of `X`s
        accept_iterator(complex_iterator);
    }
    

    虽然它不是此任务的专用方法,但它以更惯用的方式完成您想要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-10
      • 2019-02-14
      • 1970-01-01
      相关资源
      最近更新 更多