简体   繁体   English

Scala可以注意到路径依赖类型之间的身份吗?

[英]Can Scala notice identities between path-dependent types?

Sometimes in Scala I find that I get type mismatches related to path-dependent types, but I can easily reason that in fact the types coincide. 有时在Scala中我发现我得到与路径依赖类型相关的类型不匹配,但我可以轻易地推断出事实上类型是一致的。 Here's a simple example: 这是一个简单的例子:

trait Foo { trait Bar }

object Main extends App {
  val foo1 = new Foo { }
  val foo2 = foo1

  def turkle(x: foo1.Bar) {}

  turkle(new foo2.Bar {})
}

which gives: "type mismatch; found : java.lang.Object with Main.foo2.Bar required: Main.foo1.Bar". 它给出:“类型不匹配;找到:需要Main.foo2.Bar的java.lang.Object:Main.foo1.Bar”。

Now of course the paths Main.foo1.Bar and Main.foo2.Bar must coincide, since we wrote val foo2 = foo1 . 当然, Main.foo1.BarMain.foo2.Bar路径必须重合,因为我们写了val foo2 = foo1 We can verify this, by changing the last line to 我们可以通过将最后一行更改为来验证这一点

turkle((new foo2.Bar {}).asInstanceOf[foo1.Bar])

which both compiles and runs without an exception. 这两个编译和运行没有例外。

Can Scala automatically perform reasoning like this? Scala可以自动执行这样的推理吗? If so, how can I make this happen? 如果是这样,我怎么能做到这一点?

(And if not, are there any prospects for extending the type system in this direction?) (如果没有,是否有任何前景可以向这个方向扩展类型系统?)

I'll note that sometimes Scala does appear to perform this sort of reasoning. 我会注意到, 有时斯卡拉确实出现执行这种推理。 Supposing I change trait Foo to object Foo : 假设我将trait Foo改为object Foo

object Foo { trait Bar }

object Main extends App {
  val foo1 = Foo
  val foo2 = foo1

  def turkle(x: foo1.Bar) {}

  turkle(new foo2.Bar {})
}

Now everything compiles fine: somehow Scala has worked out that both Main.foo1.Bar and Main.foo2.Bar are really the same as Foo.Bar . 现在一切编译罚款,不知怎地,斯卡拉已经制定了这两个Main.foo1.BarMain.foo2.Bar真的一样Foo.Bar

Iulian Dragos gave the answer you need in a recent question. Iulian Dragos在最近的一个问题中给出了你需要的答案 The short version is that the compiler doesn't do flow analysis, so in your first example it can't tell that foo1.Bar and foo2.Bar are the same type since foo1 and foo2 are just of type Foo. 简短的版本是编译器不进行流分析,所以在你的第一个例子中它不能告诉foo1.Bar和foo2.Bar是相同的类型,因为foo1和foo2只是Foo类型。 But in the second example foo1 is inferred to be the singleton type Foo.type (a subtype of Foo), so things work as expected. 但是在第二个例子中,foo1被推断为单例类型Foo.type(Foo的子类型),因此事情按预期工作。

You can make your first example work by declaring foo2 as being the singleton type of foo1: 您可以通过将foo2声明为foo1的单例类型来使您的第一个示例工作:

val foo2:foo1.type = foo1

See section 3.2.1 of the Scala Language Specification 2.9 for reference. 请参阅Scala语言规范2.9的第3.2.1节以供参考。

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

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