繁体   English   中英

了解从属类型

[英]Understanding Dependent Types

鉴于:

scala> sealed trait Parent 
defined trait Parent

scala> case object Boy extends Parent
defined object Boy

scala> case object Girl extends Parent
defined object Girl

scala> trait F {
     |  type A 
     |  def x: A
     | }
defined trait F

scala> case object FImpl extends F {
     |  override type A = Parent
     |  def x: Parent = Boy
     | }
defined object FImpl

然后,我定义了一个方法:

scala> def foobar(f: F)(matcher: f.A => Boolean): Boolean = 
     |   matcher(f.x)
foobar: (f: F)(matcher: f.A => Boolean)Boolean

scala> foobar(FImpl)(_ match { case Boy => true; case Girl => false})
res3: Boolean = true

我对这是如何工作感到困惑。 编译器必须在编译时知道fA的类型吗?

您的问题基本上是:当f是运行时值时,编译器如何看到成员fA 答案是事实并非如此。 从语法上讲, fA看起来像是在访问f的成员,但实际上,它仅依赖于f的类型。

当你写:

object FImpl extends F {
  override type A = Parent
  def x: Parent = Boy
}

FImpl定义了一个新的单例类型,称为FImpl.type 因此, FImpl.type#AParent

调用foobarf.type被标识为FImpl.type ,因此fA aka f.type#A就是FImpl.type#A aka Parent

考虑以下两个示例:

def needsParent(p: Parent) = ???
def foobar(f: F)(matcher: f.A => Boolean) = ???

foobar(FImpl)(needsParent) // Works
foobar(FImpl: F)(needsParent) // Does not work

尽管运行时值相同,但类型不同,因此编译器接受一个并拒绝另一个。

换句话说,Scala的从属类型是一个巧妙的虚构-实际上,类型从不依赖于实际的运行时值。 但是事实证明,仅通过将类型与其他类型标识在一起,就可以在有限的范围内跟踪值,从而给依赖于值的类型留下印象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM