简体   繁体   English

了解从属类型

[英]Understanding Dependent Types

Given: 鉴于:

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

I then defined a method: 然后,我定义了一个方法:

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

I'm confused as to how this works. 我对这是如何工作感到困惑。 The compiler must know fA 's type at compile-time then? 编译器必须在编译时知道fA的类型吗?

Your question is basically: How can the compiler see the member fA when f is a runtime value? 您的问题基本上是:当f是运行时值时,编译器如何看到成员fA The answer is that it doesn't. 答案是事实并非如此。 Syntactically, fA looks like it is accessing a member of f , but in fact it is relying only on the type of f . 从语法上讲, fA看起来像是在访问f的成员,但实际上,它仅依赖于f的类型。

When you write: 当你写:

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

FImpl defines a new singleton type, known as FImpl.type . FImpl定义了一个新的单例类型,称为FImpl.type So, FImpl.type#A is Parent . 因此, FImpl.type#AParent

When you call foobar , f.type is identified with FImpl.type , so fA aka f.type#A is FImpl.type#A aka Parent . 调用foobarf.type被标识为FImpl.type ,因此fA aka f.type#A就是FImpl.type#A aka Parent

Consider these two examples: 考虑以下两个示例:

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

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

Although the runtime values are the same, the types differ, and so the compiler accepts one and rejects the other. 尽管运行时值相同,但类型不同,因此编译器接受一个并拒绝另一个。

In other words, Scala's dependent types are a clever fiction -- in fact, types never depend on actual runtime values. 换句话说,Scala的从属类型是一个巧妙的虚构-实际上,类型从不依赖于实际的运行时值。 But it turns out that just by identifying types with other types, it becomes possible to keep track of values to a limited extent, giving the impression of types that depend on values. 但是事实证明,仅通过将类型与其他类型标识在一起,就可以在有限的范围内跟踪值,从而给依赖于值的类型留下印象。

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

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