简体   繁体   English

Scala 3:处理路径相关类型

[英]Scala 3: dealing with path dependent types

Consider the following snippet:考虑以下代码段:

object Test extends App {
  class X {
    class Y
  }

  class Z(val x: X) {
    val y: x.Y = new x.Y
  }

  val x: X = new X
  val z: Z = new Z(x)
  val y: x.Y = z.y

  println(y)
}

This code won't compile, complaing about incompatible path-dependent types:此代码不会编译,抱怨不兼容的路径相关类型:

[error] 12 |  val y: x.Y = z.y
[error]    |               ^^^
[error]    |               Found:    (Test.z.y : Test.z.x.Y)
[error]    |               Required: Test.x².Y
[error]    |
[error]    |               where:    x  is a value in class Z
[error]    |                         x² is a value in object Test
[error]    |

Is there a way to gently remind the compiler that zx is assigned to x just one line above?有没有办法温和地提醒编译器zx仅在上面一行被分配给x

Even if (zx == x) { val y: xY = zy } does not solve the issue, even though path equivalence should be inferred from control flow.即使if (zx == x) { val y: xY = zy }不能解决问题,即使应该从控制流中推断出路径等价。

Background: Scala 3 macro API heavily uses PDT's, and this creates huge amount of pain to deal with --- all this pain is coming from compiler's inability to infer anything, and lack of syntactic structures to explicitly control that inference.背景: Scala 3 宏 API 大量使用 PDT,这给处理带来了巨大的痛苦——所有这些痛苦都来自编译器无法推断任何东西,以及缺乏显式控制该推断的句法结构。

This is correct behavior for path-dependent types (by the way, in Scala 2 it's the same).这是路径相关类型的正确行为(顺便说一句,在 Scala 2 中是相同的)。

Would you be satisfied with你会满意吗

val y: z.x.Y = z.y // compiles

? ?

zx equals x but this doesn't mean that the type zxY is xY . zx等于x但这并不意味着zxY类型是xY

Similarly,相似地,

class A {
  type T
}
val a = new A
val a1 = a
//implicitly[a.T =:= a1.T] // doesn't compile

a equals to a1 but this doesn't mean that the type aT is a1.T . a等于a1但这并不意味着aT类型是a1.T

This is Scala 2 spec for equivalence of path-dependent types: https://scala-lang.org/files/archive/spec/2.13/03-types.html#equivalence .这是 Scala 2 规范,用于路径相关类型的等效性: https://scala-lang.org/files/archive/spec/2.13/03-types.html#equivalence In our case the prefixes have different singleton types:在我们的例子中,前缀有不同的 singleton 类型:

implicitly[z.x.type =:= x.type] // doesn't compile
  • If a path p has a singleton type q.type , then p.type ≡ q.type .如果路径p具有 singleton 类型q.type ,则p.type ≡ q.type
  • If O is defined by an object definition, and p is a path consisting only of package or object selectors and ending in O , then O.this.type ≡ p.type .如果O由 object 定义定义,并且p是仅包含 package 或 ZA8CFDE6331BD59EB2AC96F8911BD59EB2AC96F8911BD59EB2AC96F8911BD59EB2AC96F8911BD59EB2AC96F8911B666Z 选择器并以O结尾的路径,则O.this.type ≡ p.type .

You can fix the compilation:您可以修复编译:

class A {
  type T
}
val a = new A
val a1: a.type = a
implicitly[a.T =:= a1.T] // compiles

and

class X {
  class Y
}

class Z(val x: X) {
  type V = x.Y // added
  val y: V = new x.Y
}

val x: X = new X
val z: Z = new Z(x)
val y: z.V = z.y // compiles

See also:也可以看看:

In the latest release of scala (2.12.x), is the implementation of path-dependent type incomplete? 最新发布的scala(2.12.x)中,路径依赖类型的实现是否不完整?

Cannot prove equivalence with a path dependent type 无法证明与路径相关类型的等价性

Force dependent types resolution for implicit calls 强制隐式调用的依赖类型解析

How to help the Scala 3 compiler infer a path-dependent-type? 如何帮助 Scala 3 编译器推断路径相关类型?

How to create an instances for typeclass with dependent type using shapeless 如何使用无形为具有依赖类型的类型类创建实例

If you use REPL you'll see the types inferred by the compiler (removing explicit type annotations as @LuisMiguelMejíaSuárez advised in comments):如果您使用 REPL,您将看到编译器推断的类型(删除显式类型注释,如注释中建议的@LuisMiguelMejíaSuárez ):

scala> class X {
     |   class Y
     | }
class X

scala> class Z(val x: X) {
     |   val y: x.Y = new x.Y
     | }
class Z

scala> val x = new X
val x: X = X@6f76c2cc

scala> val z = new Z(x)
val z: Z = Z@7e62cfa3

scala> val y = z.y
val y: z.x.Y = X$Y@52bd9a27  // notice z.x, not x

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

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