存在类型如何与路径依赖类型重叠?
启动 Scala 3 存在类型已被删除,原因之一陈述为
存在类型与路径依赖类型在很大程度上重叠,因此拥有它们的收益相对较小。
鉴于“很大程度上”,所以并非总是如此,我想知道是否可以提供一个具体的例子来演示如何将存在类型重写为路径依赖类型,以及一个不可能进行这种替换的例子?
回答
假设这T是我们想要通过存在量词绑定的类型,并且F[T]是某种依赖于 的类型T,所以
type A = F[T] forSome { type T }
是我们的存在类型。
提供类型 A 的实例意味着:
- 存在某种
t可以被绑定的类型T - 存在一个类型的值
F[t]
但是我们也可以将两个组件放在一个类型中,并创建T一个依赖于路径的类型成员:
type B = { type T; val value: F[T] }
类型的实例B由相同的数据描述:
t可以通过 name 绑定的某种类型T。- 类型值
F[t]
两者的价值A和B携带大致相同的信息,主要的区别是我们如何可以访问类型T在我们的量化。在 的情况下b: B,我们可以将其作为依赖于路径的类型来获取p.T,而对于a: A,我们可以在模式匹配中使用类型变量。
这是一个示例,演示了如何在存在量化类型和路径依赖类型之间进行映射:
def example[F[_]]: Unit = {
type A = F[T] forSome { type T }
type B = { type T; val value: F[T] }
def ex2pd(a: A): B = a match {
case v: F[t] => new { type T = t; val value = v }
}
def pd2ex(b: B): A = b.value
}
(这在 2.13 上编译)
我猜想“主要”是存在的,因为与 Scala 3 / Dotty 不同,以前版本的 Scala 没有任何严格形式化的基础,所以这句话的作者可能只是不想引起这样的印象,即每个存在类型都来自2.13 可以由路径依赖类型精确表示,因为这样的声明无论如何都不能严格。
- In addition to this answer, a good discussion about this topic could be found [here](https://github.com/lampepfl/dotty/issues/4353).