嵌套特征类型,有界类型和使用as关键字的详细程度

时间:2015-04-25 09:45:26

标签: rust traits

我对使用特征中嵌套类型的 as 关键字的可读性和详细程度有疑问。

我来自C ++背景,我怀疑我的误解来自于对Haskell所使用的类型系统缺乏了解,我理解Rust使用它。

在C ++中,模板化结构用作特征,其中类型是基于模板参数定义的。嵌套可以发生在结构等中定义其他结构类型等的地方。

Rust似乎支持类似的功能。 struct MyStruct<F: Foo>是下面较大的代码段的一部分,根据提供的类型F中的类型定义成员,限定为特征Foo

struct MyStruct<F: Foo>  {
// Why does this not work?
// Surely F, being constrainted to a Foo,
//   has a type BAR, constrained to Bar<F>,
//   has a type BAZ, constrained to Baz<F>
//        data: Vec<F::BAR::BAZ>,
    data: Vec< <<F as Foo>::BAR as Bar<F>>::BAZ >,
}

简而言之,在此结构中定义成员时,似乎必须使用<<F as Foo>::BAR as Bar<F>>::BAZ为编译器提供额外的类型信息。这似乎是合理的,因为编译器必须知道F的类型才能推断其类型。然而,在我看来,这些信息已经由这些类型的边界提供,在结构的泛型参数内,以及在特征定义本身内。

我发现<<F as Foo>::BAR as Bar<F>>::BAZF::BAR::BAZ相比有点难以阅读,我想知道从代码可读性的角度来看是否还有更好的处理方法?下面的完整代码片段:

use std::vec::{Vec};

pub trait Foo {
    type VALUE;
    type BAR: Bar<Self>;
}

pub trait Bar<F: Foo> {
    type BAZ: Baz<F>;    
}

pub trait Baz<F: Foo> {
    fn new(value: F::VALUE) -> Box<F::VALUE> {
        Box::new(value)
    }
}

fn main() {
    struct BarImpl;

    impl<F: Foo> Bar<F> for BarImpl {
        type BAZ = BazImpl;
    }

    struct FooImpl;

    impl Foo for FooImpl {
        type VALUE = f64;
        type BAR = BarImpl;
    }

    struct BazImpl { dummy: i32 };

    impl<F: Foo> Baz<F> for BazImpl {};


    struct MyStruct<F: Foo>  {
    // Why does this not work?
    // Surely F, being constrainted to a Foo,
    //   has a type BAR, constrained to Bar<F>,
    //   has a type BAZ, constrained to Baz<F>
    //        data: Vec<F::BAR::BAZ>,
        data: Vec< <<F as Foo>::BAR as Bar<F>>::BAZ >,
    }

    let mut s = MyStruct::<FooImpl> { data: Vec::new() };

    for x in 0..5 {
        let b = BazImpl{ dummy: x};
        s.data.push(b);
    }

    println!("s.data.len() = {}", s.data.len());
}

2 个答案:

答案 0 :(得分:3)

可以暗示第一级,因此您可以拥有Vec<<F::BAR as Bar<F>>::BAZ>。很有可能在未来规则将被放松,以便它可以应对推断多个级别的适当约束,但现在情况并非如此。

答案 1 :(得分:0)

您可以创建type alias

type FooBarBaz<F> = <<F as Foo>::BAR as Bar<F>>::BAZ;

struct MyStruct<F: Foo>  {
    data: Vec< FooBarBaz<F> >,
}