类型擦除

badge

类型擦除是将类型参数设置为 _ 并故意丢弃其信息的过程。类型擦除是许多多态语言的特性,但在 Erg 的语法上下文中,将其称为类型参数擦除更为准确

类型擦除的最常见示例是 [T, _]。数组在编译时并不总是知道它们的长度。例如,引用命令行参数的 sys.argv 的类型为 [Str, _]。由于 Erg 的编译器无法知道命令行参数的长度,因此必须放弃有关其长度的信息 然而,一个已经被类型擦除的类型变成了一个未被擦除的类型的父类型(例如[T; N] <: [T; _]),所以它可以接受更多的对象 类型的对象[T; N] 当然可以使用 [T; _],但使用后会删除N信息。如果长度没有改变,那么可以使用[T; N] 在签名中。如果长度保持不变,则必须由签名指示

# 保证不改变数组长度的函数(例如,排序)
f: [T; N] -> [T; N] # 没有的函数 (f: [T; N])
# 没有的功能(例如过滤器)
g: [T; n] -> [T; _]

如果您在类型规范本身中使用 _,则类型将向上转换为 Object 对于非类型类型参数(Int、Bool 等),带有 _ 的参数将是未定义的

i: _ # i: Object
[_; _] == [Object; _] == Array

类型擦除与省略类型说明不同。一旦类型参数信息被删除,除非您再次声明它,否则它不会被返回

implicit = (1..5).iter().map(i -> i * 2).to_arr()
explicit = (1..5).iter().map(i -> i * 2).into(Array(Nat))

在 Rust 中,这对应于以下代码:


#![allow(unused)]
fn main() {
let partial = (1..6).iter().map(|i| i * 2).collect::<Vec<_>>();
}

Erg 不允许部分省略类型,而是使用高阶种类多态性

# collect 是采用 Kind 的高阶 Kind 方法
hk = (1..5).iter().map(i -> i * 2).collect(Array)
hk: Array(Int)