Generics 实现不只是impl-Foo有技术原因吗?

Generics 实现不只是impl-Foo有技术原因吗?,generics,syntax,rust,Generics,Syntax,Rust,我刚刚了解到,使用泛型的结构被声明为struct Foo,而实现被声明为impl Foo。以下是对差异的解释: 注意,我们必须在impl之后声明T,以便在类型点中使用T。在impl之后将T声明为泛型类型是Rust如何知道尖括号中的类型是泛型类型而不是具体类型的 再说一次,我是个新手,但是对于必须声明struct Foo,甚至可能是fn foobar:t,难道不能提出同样的理由吗 这将是三个impl块,分别具有名为T、i32和u32的类型参数 你可能会说,根据上下文来决定。现在,为了弄清发生了什么

我刚刚了解到,使用泛型的结构被声明为struct Foo,而实现被声明为impl Foo。以下是对差异的解释:

注意,我们必须在impl之后声明T,以便在类型点中使用T。在impl之后将T声明为泛型类型是Rust如何知道尖括号中的类型是泛型类型而不是具体类型的

再说一次,我是个新手,但是对于必须声明struct Foo,甚至可能是fn foobar:t,难道不能提出同样的理由吗

这将是三个impl块,分别具有名为T、i32和u32的类型参数

你可能会说,根据上下文来决定。现在,为了弄清发生了什么,用户不仅要检查模块的其余部分,还要检查所有导入的符号和标准库前奏曲中的任何内容,以确定类型是否为参数。Rust厌恶这种模糊性

对于编译器和读者来说,明确什么是参数和什么不是参数要简单得多

不必对struct执行此操作,因为括号中的内容不可能是类型参数声明之外的任何内容

这将是三个impl块,分别具有名为T、i32和u32的类型参数

你可能会说,根据上下文来决定。现在,为了弄清发生了什么,用户不仅要检查模块的其余部分,还要检查所有导入的符号和标准库前奏曲中的任何内容,以确定类型是否为参数。Rust厌恶这种模糊性

对于编译器和读者来说,明确什么是参数和什么不是参数要简单得多

您不必对struct执行此操作,因为括号中的内容不可能是除类型参数声明之外的任何内容。

除了的答案之外,我还想比较Rust是如何执行此操作的,Haskell是如何执行此操作的

在Haskell中,所有特定类型都必须以大写开头。因此,写以下内容是非法的:

数据mytype Var=构造函数{ myVar::Var, myInt::Foo } 相反,Haskell为类型变量保留以小写字母开头的类型:

数据MyType var=构造函数{ myVar::var myInt::Int } 实例MyClass MyType变量,其中 ... 这里,var是一个类型变量,MyType是具体的,Int是具体的

在我看来,Rust犯了一个错误,允许使用非大写的类型标识符。因此,该语言别无选择,只能要求您明确指出哪些类型标识符是变量,哪些是特定的。可以说Rust的明确性提高了可读性。也可以提出相反的观点

当然,Rust可能会添加一个假设特征,您可能会说:

 impl Foo<#T, T, u32> { .. }
这里,前缀表示这是一个类型变量,因此T是一个类型变量,T是特定的,u32是特定的。没有歧义,只需要局部推理

有了这个功能,你可能会少一点赘述,但我坚信这艘船已经航行了——现在添加这个功能只会增加另一种做同样事情的方式,但收获很少。但是,这项功能会增加另一项语言用户必须学习的功能的成本。

除了用户的答案之外,我想比较一下Rust和Haskell是如何做到的

在Haskell中,所有特定类型都必须以大写开头。因此,写以下内容是非法的:

数据mytype Var=构造函数{ myVar::Var, myInt::Foo } 相反,Haskell为类型变量保留以小写字母开头的类型:

数据MyType var=构造函数{ myVar::var myInt::Int } 实例MyClass MyType变量,其中 ... 这里,var是一个类型变量,MyType是具体的,Int是具体的

在我看来,Rust犯了一个错误,允许使用非大写的类型标识符。因此,该语言别无选择,只能要求您明确指出哪些类型标识符是变量,哪些是特定的。可以说Rust的明确性提高了可读性。也可以提出相反的观点

当然,Rust可能会添加一个假设特征,您可能会说:

 impl Foo<#T, T, u32> { .. }
这里,前缀表示这是一个类型变量,因此T是一个类型变量,T是特定的,u32是特定的。没有歧义,只需要局部推理

有了这个功能,你可能会少一点赘述,但我坚信这艘船已经航行了——现在添加这个功能只会增加另一种做同样事情的方式,但收获很少。但是,该功能会增加另一个语言用户必须学习的功能的成本。

我猜这是因为impl-Foo已经意味着
其他事情:为一个名为T的特定类型实现Foo泛型。想象一下相反的情况:impl Foo是指为32位整数实现Foo,还是为任何名为i32的类型参数实现Foo?在您提到的其他情况下,这种模糊性并不存在。@millimoose:所以在某些情况下表示泛型,而在某些情况下表示特定类型?如果不熟悉语法,似乎很难知道我在处理哪一个。这并不比。。。定义函数和调用函数的方式。如果您不熟悉它的语法,我不确定您在任何语言中如何有效。@l0b0假设我们使用«»来声明泛型和使用特定类型,那么您必须编写结构Foo«T»和impl«T»Foo。这真的会让事情变得更清楚吗?我猜这是因为impl Foo已经意味着其他东西:为一个特定类型实现Foo泛型类型,称为T。想象一下相反的情况:impl Foo是为32位整数实现Foo,还是为任何名为i32的类型参数实现Foo?在您提到的其他情况下,这种模糊性并不存在。@millimoose:所以在某些情况下表示泛型,而在某些情况下表示特定类型?如果不熟悉语法,似乎很难知道我在处理哪一个。这并不比。。。定义函数和调用函数的方式。如果您不熟悉它的语法,我不确定您在任何语言中如何有效。@l0b0假设我们使用«»来声明泛型和使用特定类型,那么您必须编写结构Foo«T»和impl«T»Foo。这真的能让事情更清楚吗?谢谢,这就澄清了。我想我的困惑源于歧义,有时是泛型,有时是特定类型。谢谢,这澄清了这一点。我猜我的困惑源于歧义,有时是泛型,有时是特定类型。这是一个很好的比较和总结!很好的比较和总结了这个问题!
 impl Foo<#T, T, u32> { .. }