带有类型成员的对象:Scala的对象与模块系统是什么?(试图理解2014年Odersky关于路径依赖类型的论文)



我正在阅读路径相关类型的基础。在第一页的右栏上写着:

我们的动机是双重的。首先,我们相信具有类型成员的对象未被完全理解。目前尚不清楚是什么导致了复杂性,哪些复杂部分对概念至关重要或是偶然的到试图实现的语言实现或微积分其他的东西。其次,我们认为具有类型成员的对象真的很有用。它们可以编码各种其他的,通常是分开的类型系统功能。最重要的是,它们统一了对象和模块系统,通过在其他结构系统中添加名词性的概念。

有人能澄清/解释"对象与模块"系统的含义吗?

或者一般来说,是什么

"它们(具有类型成员的对象)统一了对象和模块系统,通过在其他结构系统中添加名词性的概念。">

平均值?

什么概念?从哪里?

对象名称/值的名义性?类型中的结构?或者反过来?

这里的类型成员属于哪里?到模块系统?对象系统?怎样为什么?

编辑:

这种统一与依赖路径的类型有什么关系?在我看来,它们允许这种统一(具有类型成员的对象)发生。是这样吗?如果是,如何?

你能举一个简单的例子说明这意味着什么吗?(即,允许模块和对象系统统一的路径相关类型与如果我们没有路径相关类型,为什么不可能实现统一?)

编辑2:

来自论文:

要使用类型成员,程序员需要一种方法来引用他们这意味着类型必须能够引用对象,即。包含用作一组动态的静态近似的项对象。换句话说,需要某种程度的依赖类型;通常的概念是路径相关类型。

所以我到目前为止的理解(在Jesper的回答的帮助下):

上面的这一段部分回答了上面的一些问题。主要的方法似乎是让对象具有类型成员,并且需要依赖路径的类型,因为对象是动态/运行时依赖的,但类型是静态的(在编译时定义),所以仅仅通过拥有导致类型成员的对象是不起作用的,因为这样在编译时就不会清楚地定义这些类型成员。

依赖路径的类型通过在编译时固定指向类型成员的路径(通过要求对象在编译时已经已知/定义)来提供帮助,因此即使路径经过对象(在编译时可能会发生变化),但如果这些对象在编译期间已经固定,那么它们的类型成员在编译时也可以有明确的含义。

我不确定我是否完全理解你的问题,但我会尝试一下。:)我认为作者主要指的是ML风格的模块,其中签名对应Scala特性,结构对应Scala对象。Scala统一了记录值、对象和模块的概念,而在大多数其他语言(如ML、Rust等)中,这些概念是独立的概念。主要的好处是,在Scala中,模块/对象可以作为普通函数参数传递(而在ML中,必须使用特殊的函子)。

在ML中,模块根据其结构(类似于Scala中的结构类型)检查与签名(Scala中为trait)的兼容性,但在Scala中,模块必须通过名称(名义类型)实现trait。因此,即使两个模块/对象在Scala中具有相同的结构,它们也可能不兼容,这取决于它们的超类型层次结构。

Scala中关于类型成员的一个非常强大的特性是,即使你不知道它的类型成员的确切类型,你也可以使用一个特性,只要你以类型安全的方式来使用它(我认为这在ML模块中也是可能的),例如:

trait A {
type X
def getX: X
def setX(x: X): Unit
}
def foo(a: A) = a.setX(a.getX)

foo中,Scala编译器不知道a.X的确切类型,但该类型的值仍然可以以编译器知道安全的方式使用。例如,这在Rust中是不可能的。

Scala编译器的下一个版本Dotty将基于您参考的论文中描述的理论。这种模块和对象与子类型、特征和类型成员相结合的统一是Scala独特且非常强大的原因之一。

编辑:为了进一步解释路径依赖类型增加Scala模块/对象系统灵活性的原因,让我们用来扩展上面的例子

def bar(a: A, b: A) = a.setX(b.getX)

这将导致编译错误:

error: type mismatch;
found   : b.T
required: a.T
def foo(a: A, b: A) = a.setX(b.getX)
^

并且是正确的,因为CCD_ 3和CCD_。你可以通过使用路径相关类型来修复它:

def bar(a: A)(b: A { type X = a.X }) = a.setX(b.getX)

或者添加一个类型参数:

def bar[T](a: A { type X = T }, b: A { type X = T }) = a.setX(b.getX)

因此,路径依赖类型消除了对类型参数的一些需求,也允许我们有效地表达存在类型(如果A有类型参数而不是类型成员,则对应于A[_]A[T] forSome { type T })。

最新更新