Rust中的traits和Haskell中的类型类有什么区别?

问题描述 投票:135回答:3

Rust中的Traits似乎至少表面上与Haskell中的typeclasses类似,但是我看到人们写道他们之间存在一些差异。我想知道这些差异究竟是什么。

haskell rust traits
3个回答
56
投票

在基础层面上,没有太大区别,但它们仍然存在。

Haskell将类型类中定义的函数或值描述为“方法”,就像traits在它们所包含的对象中描述OOP方法一样。但是,Haskell以不同的方式处理这些问题,将它们视为单独的值而不是将它们固定到对象上,因为OOP会引导人们去做。这是关于最明显的表面水平差异。

直到最近,Rust无法做到的一件事是高阶类型的特征,例如臭名昭​​着的FunctorMonad类型。

这意味着Rust特征只能描述通常所谓的“具体类型”,换句话说,没有通用参数。但是,Haskell可以生成高阶类型类,它使用类似于高阶函数如何使用其他函数的类型,使用一个来描述另一个函数。我们无法实现Rust中提到的类型类,因为它不支持在Haskell中被认为是基本的,甚至是必不可少的这个特性。值得庆幸的是,这最近已经与associated items一起实施。*但是,这不是惯用的Rust,通常被认为是'hack'。

如评论中所述,GHC(Haskell的主要编译器)支持类型类的更多选项,包括multi-parameter(即涉及的许多类型)类型类,以及functional dependencies,一个允许类型级计算的可爱选项,以及引导,这也是值得一提的。到type families。据我所知,Rust既没有funDeps也没有打字系列,虽然它可能在未来。†

总而言之,虽然表面上的特征和类型似乎相当,但在考虑众多品质时,它们在进行更深入比较时确实存在很多差异。


*另一方面,Swift尽管有特质,却没有这种更高级别的机制。可能是未来的语言更新?

†关于Haskell的类型类(包括更高类型的类型)的一篇很好的文章可以找到here,并且在Rust的特性上同样好的文章是here,但不幸的是有点过时了。


13
投票

我认为当前的答案忽略了Rust traits和Haskell类型类之间最根本的区别。这些差异与特征与面向对象的语言结构相关的方式有关。有关此信息,请参阅Rust book

  1. 特征声明会创建特征类型。这意味着您可以声明此类型的变量(或者更确切地说,类型的引用)。您还可以使用特征类型作为函数,结构字段和类型参数实例化的参数。 特征引用变量可以在运行时包含不同类型的对象,只要引用对象的运行时类型实现特征即可。 // The shape variable might contain a Square or a Circle, // we don't know until runtime let shape: &Shape = get_unknown_shape(); // Might contain different kinds of shapes at the same time let shapes: Vec<&Shape> = get_shapes(); 这不是类型类的工作方式。类型类不创建任何类型,因此您无法使用类名声明变量。类型类充当类型参数的边界,但类型参数必须使用具体类型实例化,而不是类型类本身。 您不能拥有实现相同类型类的不同类型的不同事物的列表。 (相反,在Haskell中使用存在类型来表达类似的东西。)注1
  2. 可以动态调度特征方法。这与上一节中描述的内容密切相关。 动态分派意味着参考点的对象的运行时类型用于确定通过引用调用的方法。 let shape: &Shape = get_unknown_shape(); // This calls a method, which might be Square.area or // Circle.area depending on the runtime type of shape print!("Area: {}", shape.area()); 同样,在Haskell中使用存在类型。

In Conclusion

在我看来,特征与类型类基本上是相同的概念。此外,它们还具有面向对象接口的功能。

另一方面,Haskell的类型类更高级,因为Haskell具有例如更高级的类型和扩展,如多参数类型类。但我认为它们基本相同。


注1:Rust的最新版本有一个更新,用于将特征名称的用法区分为类型,将特征名称的用法区分为边界。在特征类型中,名称以dyn关键字为前缀。有关更多信息,请参阅此answer


8
投票

Rust的“特征”类似于Haskell的类型类。

与Haskell的主要区别在于,traits只干涉带点符号的表达式,即a.foo(b)形式。

Haskell类型类扩展到更高阶类型。 Rust特征只支持更高阶类型,因为它们在整个语言中都缺失,即它不是特征和类型类之间的哲学差异

© www.soinside.com 2019 - 2024. All rights reserved.