Dotty 如何对多态方法进行脱糖?
How does Dotty desugar polymorphic methods?
据报道,Dotty 将具有类型参数的 类 脱糖为具有类型成员的 类,例如:
class C[T, U] { }
// <=>
class C {
type C$T
type C$U
}
Dotty 如何像下面的示例那样对多态方法进行脱糖?
def m[T, U](x: T, u: U): T = x
// <=>
?
与多态 类 不同,多态 方法 不会脱糖。它们基本上保持多态性。
您可能需要从最新的 DOT 论文第 13 页第 5.2 节的底部开始 The Essence of DOT by Nada Amin, Samuel Grütter, Martin Odersky, Tiark Rompf, and Sandro Stucki。它展示了 Scala 中简单协变多态 List[+A]
类型的实现。特别值得注意的是多态cons[A]
方法:
package scala.collection.immutable
trait List[+A] {
def isEmpty: Boolean
def head: A
def tail: List[A]
}
object List {
def cons[A](hd: A, tl: List[A]) = new List[A] {
def isEmpty = false
def head = hd
def tail = tl
}
}
以及它在 DOT 中的编码方式:
let scala_collection_immutable = ν(sci) {
List = μ(self: {A; isEmpty: bool.Boolean; head: self.A; tail: sci.List∧{A <: self.A}})
cons: ∀(x: {A})∀(hd: x.A)∀(tl: sci.List∧{A <: x.A})sci.List∧{A <: x.A} =
λ(x: {A})λ(hd: x.A)λ(tl: sci.List∧{A <: x.A})
let result = ν(self) {
A = x.A; isEmpty = bool.false; head = hd; tail = tl }
in result
}: { μ(sci: {
List <: μ(self: {A; head: self.A; tail: sci.List∧{A <: self.A}})
cons: ∀(x: {A})∀(hd: x.A)∀(tl: sci.List∧{A <: x.A})sci.List∧{A <: x.A}
})}
in …
这反过来会让您直观地了解它是如何在 Dotty 中编码的。
然后第 15 页向您展示了如何将脱糖 DOT 映射回 Scala:
object scala_collection_immutable { sci =>
trait List { self =>
type A
def isEmpty: Boolean
def head: self.A
def tail: List{type A <: self.A}
}
def cons(x: {type A})(hd: x.A)(tl: sci.List{type A <: x.A})
: sci.List{type A <: x.A} = new List{ self =>
type A = x.A
def isEmpty = false
def head = hd
def tail = tl
}
}
如您所见,多态方法的编码与多态特征或多或少相同:类型参数成为抽象类型成员,在这种情况下是细化类型的抽象类型成员(又名结构类型):
x : A
// becomes
x : {type A}
据报道,Dotty 将具有类型参数的 类 脱糖为具有类型成员的 类,例如:
class C[T, U] { }
// <=>
class C {
type C$T
type C$U
}
Dotty 如何像下面的示例那样对多态方法进行脱糖?
def m[T, U](x: T, u: U): T = x
// <=>
?
与多态 类 不同,多态 方法 不会脱糖。它们基本上保持多态性。
您可能需要从最新的 DOT 论文第 13 页第 5.2 节的底部开始 The Essence of DOT by Nada Amin, Samuel Grütter, Martin Odersky, Tiark Rompf, and Sandro Stucki。它展示了 Scala 中简单协变多态 List[+A]
类型的实现。特别值得注意的是多态cons[A]
方法:
package scala.collection.immutable
trait List[+A] {
def isEmpty: Boolean
def head: A
def tail: List[A]
}
object List {
def cons[A](hd: A, tl: List[A]) = new List[A] {
def isEmpty = false
def head = hd
def tail = tl
}
}
以及它在 DOT 中的编码方式:
let scala_collection_immutable = ν(sci) {
List = μ(self: {A; isEmpty: bool.Boolean; head: self.A; tail: sci.List∧{A <: self.A}})
cons: ∀(x: {A})∀(hd: x.A)∀(tl: sci.List∧{A <: x.A})sci.List∧{A <: x.A} =
λ(x: {A})λ(hd: x.A)λ(tl: sci.List∧{A <: x.A})
let result = ν(self) {
A = x.A; isEmpty = bool.false; head = hd; tail = tl }
in result
}: { μ(sci: {
List <: μ(self: {A; head: self.A; tail: sci.List∧{A <: self.A}})
cons: ∀(x: {A})∀(hd: x.A)∀(tl: sci.List∧{A <: x.A})sci.List∧{A <: x.A}
})}
in …
这反过来会让您直观地了解它是如何在 Dotty 中编码的。
然后第 15 页向您展示了如何将脱糖 DOT 映射回 Scala:
object scala_collection_immutable { sci =>
trait List { self =>
type A
def isEmpty: Boolean
def head: self.A
def tail: List{type A <: self.A}
}
def cons(x: {type A})(hd: x.A)(tl: sci.List{type A <: x.A})
: sci.List{type A <: x.A} = new List{ self =>
type A = x.A
def isEmpty = false
def head = hd
def tail = tl
}
}
如您所见,多态方法的编码与多态特征或多或少相同:类型参数成为抽象类型成员,在这种情况下是细化类型的抽象类型成员(又名结构类型):
x : A
// becomes
x : {type A}