[英]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#A
是Parent
。
When you call foobar
, f.type
is identified with FImpl.type
, so fA
aka f.type#A
is FImpl.type#A
aka Parent
. 调用foobar
, f.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.