具有路径依赖类型和协变参数的Scala复制类

具有路径依赖类型和协变参数的Scala复制类,scala,covariance,path-dependent-type,Scala,Covariance,Path Dependent Type,我在路径依赖类型和协变参数方面遇到了一些问题。我需要创建SomeFancyCollection的一个新实例,但由于路径依赖类型,它无法编译。当我把节点和分支之类的东西都从类中取出时,我必须将根参数声明为private[this],而且Iam也无法获得该类的新实例。 我的代码如下所示: class SomeFancyCollection[+A] { private var root: Node = Branch(0x0, Vector[Node]()) trait Node {

我在路径依赖类型和协变参数方面遇到了一些问题。我需要创建SomeFancyCollection的一个新实例,但由于路径依赖类型,它无法编译。当我把节点和分支之类的东西都从类中取出时,我必须将根参数声明为private[this],而且Iam也无法获得该类的新实例。 我的代码如下所示:

class SomeFancyCollection[+A] {

  private var root: Node = Branch(0x0, Vector[Node]())

  trait Node {
    val id: Byte
    def put[A1 >: A](ids: Seq[Byte], item: A1): Node
    def remove[A1 >: A](ids: Seq[Byte], item: A1): Node
  }

  case class Branch(id: Byte, subs: Vector[Node]) extends Node {
      ...
  }

  case class Leaf[A1 >: A](id: Byte, subs: Vector[A1]) extends Node {
      ...
  }

  def add[A1 >: A](item: A1): SomeFancyCollection[A1] = {
    val ids: Seq[Byte] = getIds() // doesn't matter
    val newRoot = root.put(ids, item)
    val newInstance = new SomeFancyCollection[A1]()
    newInstance.root = newRoot
    newInstance
  }
}

在代码中,没有明显的理由创建
节点
嵌套的路径依赖类。只要让它们成为协变的独立类,那么所有与路径相关的问题就会消失:

trait Node[+A] {
  val id: Byte
  def put[A1 >: A](ids: Seq[Byte], item: A1): Node[A1]
  def remove[A1 >: A](ids: Seq[Byte], item: A1): Node[A1]
}

case class Branch[+A](id: Byte, subs: Vector[Node[A]]) extends Node[A] {

  def put[A1 >: A](ids: Seq[Byte], item: A1): Node[A1] = ???
  def remove[A1 >: A](ids: Seq[Byte], item: A1): Node[A1] = ???
}

case class Leaf[+A](id: Byte, subs: Vector[A]) extends Node[A] {

  def put[A1 >: A](ids: Seq[Byte], item: A1): Node[A1] = ???
  def remove[A1 >: A](ids: Seq[Byte], item: A1): Node[A1] = ???
}



class SomeFancyCollection[+A](val root: Node[A] = Branch(0x0, Vector[Node[A]]())) {
  def add[A1 >: A](item: A1): SomeFancyCollection[A1] = {
    val ids: Seq[Byte] = ???// getIds() // doesn't matter
    val newRoot = root.put(ids, item)
    new SomeFancyCollection[A1](newRoot)
  }
}
如果您不想污染名称空间,只需将
节点
类包声明为私有,甚至将所有辅助实现细节类隐藏在
SomeFancyCollection
的伴随对象中:

class SomeFancyCollection[+A] private[SomeFancyCollection](
  val root: SomeFancyCollection.AnnoyingDetails.Node[A]
) {
  def add[A1 >: A](item: A1): SomeFancyCollection[A1] = {
    val ids: Seq[Byte] = ???// getIds() // doesn't matter
    val newRoot = root.put(ids, item)
    new SomeFancyCollection[A1](newRoot)
  }
}

object SomeFancyCollection {

  def empty[A]: SomeFancyCollection[A] = new SomeFancyCollection[A](
    AnnoyingDetails.Branch(0x0, Vector[AnnoyingDetails.Node[A]]())
  )

  private[SomeFancyCollection] object AnnoyingDetails {
    trait Node[+A] {
      val id: Byte
      def put[A1 >: A](ids: Seq[Byte], item: A1): Node[A1]
      def remove[A1 >: A](ids: Seq[Byte], item: A1): Node[A1]
    }

    case class Branch[+A](id: Byte, subs: Vector[Node[A]]) extends Node[A] {
      def put[A1 >: A](ids: Seq[Byte], item: A1): Node[A1] = ???
      def remove[A1 >: A](ids: Seq[Byte], item: A1): Node[A1] = ???
    }

    case class Leaf[+A](id: Byte, subs: Vector[A]) extends Node[A] {
      def put[A1 >: A](ids: Seq[Byte], item: A1): Node[A1] = ???
      def remove[A1 >: A](ids: Seq[Byte], item: A1): Node[A1] = ???
    }
  }
}

这是一种路径依赖类型的点,可以防止像您这样的代码编译:每个
节点
属于一个特定的
SomeFancyCollection
实例,这里
newRoot
属于
这个
实例,不能与
newInstance
一起使用。