rust 色中的Traits看起来至少表面上与哈斯克尔中的typeclasses相似,但我看到人们写道,它们之间存在一些差异.我想知道这些区别到底是什么.

推荐答案

在基本层面上,差别不大,但仍然存在.

Haskell将typeclass中定义的函数或值描述为"方法",就像traits在它们所包含的对象中描述OOP方法一样.然而,Haskell以不同的方式处理这些问题,将它们视为单独的值,而不是像OOP那样将它们固定到对象上.这是最明显的地表差异.

Rust暂时做不到的一件事是higher-order typed traits,比如臭名昭著的FunctorMonad类型类.

这意味着 rust 病特征只能描述通常被称为"混凝土类型"的东西,换句话说,一种没有通用参数的类型.Haskell从一开始就可以创建高阶类型类,这些类使用的类型与高阶函数使用其他函数的方式类似:使用一个函数来描述另一个函数.有一段时间,这在Rust中是不可能实现的,但自从associated items个已经实现以来,这样的特性已经变得司空见惯.

因此,如果我们忽略扩展,它们并不完全相同,但每个扩展都可以近似于另一个扩展.

还值得一提的是,正如 comments 中所说,GHC(Haskell的主要编译器)支持类型类的进一步选项,包括multi-parameter个(即涉及许多类型)类型类,以及functional dependencies,这是一个可爱的选项,允许进行类型级计算,并导致type families个.据我所知,Rust既没有funDeps家族,也没有type家族,尽管将来可能会出现.†

总而言之,trait 和类型有着根本的区别,这是因为它们相互作用的方式,使它们的行为最终看起来非常相似.


†关于Haskell的TypeClass(包括更高类型的)的一篇好文章可以在here中找到,关于特性的Rust by Example章节可以在here中找到

Rust相关问答推荐

如何优化小型固定大小数组中的搜索?

go 掉包装 struct 中的泛型

在特征中使用Async时,如何解决不透明类型`impl Future<;out=self>;`不满足其关联的类型边界和警告?

除了调用`waker.wake()`之外,我如何才能确保future 将再次被轮询?

如何循环遍历0..V.len()-1何时v可能为空?

在生存期内将非静态可变引用转换为范围内的静态可变引用

在Rust中克隆源自INTO_ITER()的迭代器的成本?

Tokio';s io::用Cursor拆分<;Vec<;u8>>;赢得';t get the full writted data

如何重命名 clap_derive 中的子命令占位符?

从字节数组转换为字节元组和字节数组时,为什么 Transmute 会对字节重新排序?

Rust 如何将链表推到前面?

如何将 &[T] 或 Vec<T> 转换为 Arc<Mutex<[T]>>?

Rust中如何实现一个与Sized相反的负特性(Unsized)

Rust编译器通过哪些规则来确保锁被释放?

当在lambda中通过引用传递时,为什么会出现终身/类型不匹配错误?

使用 traits 时,borrow 的值不会存在足够长的时间

&str 的编译时拆分是否可能?

A 有一个函数,它在 Option<> 类型中时无法编译,但在 Option<> 类型之外会自行编译.为什么?

在特征中返回一个 Self 类型的值

为什么 Rust 中的关联类型需要明确的生命周期注释?