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中,我忽略了ThisTypeAbstract的子类型。我知道如果我不设置这个上限,ThisType 可以是任何东西。但是,如果我有 AbstractSet 并且我执行了它的元素的 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#ThisTypeAbstract 不同,而在 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[_] 是一个存在性的问题,它的工作方式不太一样,因此您可以插入一个常见的超类型,如图所示。