Scala 类型和 F 有界类型
Scala types and F bounded types
我正在学习 Scala 中的 F-bound 类型,我遇到过一种我不知道哪里出了问题的情况。
我做了三个测试,代码如下:
import scala.collection.mutable
def test1() = {
trait Abstract {
type ThisType <: Abstract
def deepCopy(): ThisType
}
case class Concrete1(a: Int) extends Abstract {
override type ThisType = Concrete1
override def deepCopy(): ThisType = this.copy()
}
case class Concrete2(a: Int) extends Abstract {
override type ThisType = Concrete2
override def deepCopy(): ThisType = this.copy()
}
val set = new mutable.HashSet[Abstract]()
set ++= List(Concrete1(1), Concrete2(2))
val set2: mutable.Set[Abstract] = set.map(_.deepCopy())
}
def test2() = {
trait Abstract {
type ThisType
def deepCopy(): ThisType
}
case class Concrete1(a: Int) extends Abstract {
override type ThisType = Concrete1
override def deepCopy(): ThisType = this.copy()
}
case class Concrete2(a: Int) extends Abstract {
override type ThisType = Concrete2
override def deepCopy(): ThisType = this.copy()
}
val set = new mutable.HashSet[Abstract]()
set ++= List(Concrete1(1), Concrete2(2))
val set2: mutable.Set[Abstract] = set.map(_.deepCopy())
}
def test3() = {
trait Abstract[T <: Abstract[T]] {
def deepCopy(): T
}
case class Concrete1(a: Int) extends Abstract[Concrete1] {
override def deepCopy(): Concrete1 = this.copy()
}
case class Concrete2(a: Int) extends Abstract[Concrete2] {
override def deepCopy(): Concrete2 = this.copy()
}
val set = new mutable.HashSet[Abstract[_]]()
set ++= List(Concrete1(1), Concrete2(2))
val set2: mutable.Set[Abstract[_]] = set.map(_.deepCopy())
}
test1 工作正常。 test2 和 test3 产生编译时错误。
在test2中,我忽略了ThisType
是Abstract
的子类型。我知道如果我不设置这个上限,ThisType
可以是任何东西。但是,如果我有 Abstract
的 Set
并且我执行了它的元素的 deepCopy()
,它不是同一类型吗?编译器产生此错误:
Error:(53, 45) type mismatch;
found : scala.collection.mutable.HashSet[Abstract#ThisType]
required: scala.collection.mutable.Set[Abstract]
val set2: mutable.Set[Abstract] = set.map(_.deepCopy())
^
我不明白为什么在这种情况下 (test2) Abstract#ThisType
与 Abstract
不同,而在 test1 中是。它与路径依赖类型有关吗?如果是,解释是什么?
在 test3 中,我尝试执行与 test1 中相同的操作,但使用类型参数,此编译器在第 val set2: mutable.Set[Abstract[_]] = set.map(_.deepCopy())
行抛出错误:
Error:(78, 48) type mismatch;
found : scala.collection.mutable.HashSet[Any]
required: scala.collection.mutable.Set[Abstract[_]]
Note: Any >: Abstract[_], but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ >: Abstract[_]`. (SLS 3.2.10)
val set2: mutable.Set[Abstract[_]] = set.map(_.deepCopy())
^
Error:(140, 45) type mismatch;
found : scala.collection.mutable.HashSet[Abstract#ThisType]
required: scala.collection.mutable.Set[Abstract]
val set2: mutable.Set[Abstract] = set.map(_.deepCopy())
^
Error:(166, 48) type mismatch;
found : scala.collection.mutable.HashSet[Any]
required: scala.collection.mutable.Set[Abstract[_]]
Note: Any >: Abstract[_], but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ >: Abstract[_]`. (SLS 3.2.10)
val set2: mutable.Set[Abstract[_]] = set.map(_.deepCopy())
^
是跟通配符有关的东西,但是我不知道这种没有通配符的类型怎么声明。
这是一个版本,其中显示了我的解释中的某些部分https://scalafiddle.io/sf/Wnk3ekK/2
所以 2 scalac 中的问题无法证明 Abstract
是 typemeber 的常见超类型,因为缺少边界。看到 ThisType
可以,例如是 Int
,它确实不是 Abstract
的子类型,因此不符合 Set[Abstract]
的条件
in 3 的问题是 Abstract[_]
是一个存在性的问题,它的工作方式不太一样,因此您可以插入一个常见的超类型,如图所示。
我正在学习 Scala 中的 F-bound 类型,我遇到过一种我不知道哪里出了问题的情况。
我做了三个测试,代码如下:
import scala.collection.mutable
def test1() = {
trait Abstract {
type ThisType <: Abstract
def deepCopy(): ThisType
}
case class Concrete1(a: Int) extends Abstract {
override type ThisType = Concrete1
override def deepCopy(): ThisType = this.copy()
}
case class Concrete2(a: Int) extends Abstract {
override type ThisType = Concrete2
override def deepCopy(): ThisType = this.copy()
}
val set = new mutable.HashSet[Abstract]()
set ++= List(Concrete1(1), Concrete2(2))
val set2: mutable.Set[Abstract] = set.map(_.deepCopy())
}
def test2() = {
trait Abstract {
type ThisType
def deepCopy(): ThisType
}
case class Concrete1(a: Int) extends Abstract {
override type ThisType = Concrete1
override def deepCopy(): ThisType = this.copy()
}
case class Concrete2(a: Int) extends Abstract {
override type ThisType = Concrete2
override def deepCopy(): ThisType = this.copy()
}
val set = new mutable.HashSet[Abstract]()
set ++= List(Concrete1(1), Concrete2(2))
val set2: mutable.Set[Abstract] = set.map(_.deepCopy())
}
def test3() = {
trait Abstract[T <: Abstract[T]] {
def deepCopy(): T
}
case class Concrete1(a: Int) extends Abstract[Concrete1] {
override def deepCopy(): Concrete1 = this.copy()
}
case class Concrete2(a: Int) extends Abstract[Concrete2] {
override def deepCopy(): Concrete2 = this.copy()
}
val set = new mutable.HashSet[Abstract[_]]()
set ++= List(Concrete1(1), Concrete2(2))
val set2: mutable.Set[Abstract[_]] = set.map(_.deepCopy())
}
test1 工作正常。 test2 和 test3 产生编译时错误。
在test2中,我忽略了ThisType
是Abstract
的子类型。我知道如果我不设置这个上限,ThisType
可以是任何东西。但是,如果我有 Abstract
的 Set
并且我执行了它的元素的 deepCopy()
,它不是同一类型吗?编译器产生此错误:
Error:(53, 45) type mismatch;
found : scala.collection.mutable.HashSet[Abstract#ThisType]
required: scala.collection.mutable.Set[Abstract]
val set2: mutable.Set[Abstract] = set.map(_.deepCopy())
^
我不明白为什么在这种情况下 (test2) Abstract#ThisType
与 Abstract
不同,而在 test1 中是。它与路径依赖类型有关吗?如果是,解释是什么?
在 test3 中,我尝试执行与 test1 中相同的操作,但使用类型参数,此编译器在第 val set2: mutable.Set[Abstract[_]] = set.map(_.deepCopy())
行抛出错误:
Error:(78, 48) type mismatch;
found : scala.collection.mutable.HashSet[Any]
required: scala.collection.mutable.Set[Abstract[_]]
Note: Any >: Abstract[_], but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ >: Abstract[_]`. (SLS 3.2.10)
val set2: mutable.Set[Abstract[_]] = set.map(_.deepCopy())
^
Error:(140, 45) type mismatch;
found : scala.collection.mutable.HashSet[Abstract#ThisType]
required: scala.collection.mutable.Set[Abstract]
val set2: mutable.Set[Abstract] = set.map(_.deepCopy())
^
Error:(166, 48) type mismatch;
found : scala.collection.mutable.HashSet[Any]
required: scala.collection.mutable.Set[Abstract[_]]
Note: Any >: Abstract[_], but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ >: Abstract[_]`. (SLS 3.2.10)
val set2: mutable.Set[Abstract[_]] = set.map(_.deepCopy())
^
是跟通配符有关的东西,但是我不知道这种没有通配符的类型怎么声明。
这是一个版本,其中显示了我的解释中的某些部分https://scalafiddle.io/sf/Wnk3ekK/2
所以 2 scalac 中的问题无法证明 Abstract
是 typemeber 的常见超类型,因为缺少边界。看到 ThisType
可以,例如是 Int
,它确实不是 Abstract
的子类型,因此不符合 Set[Abstract]
in 3 的问题是 Abstract[_]
是一个存在性的问题,它的工作方式不太一样,因此您可以插入一个常见的超类型,如图所示。