我对使用特征中嵌套类型的 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>>::BAZ
与F::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());
}
答案 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> >,
}