Scala DAG更新了几个parents

Scala DAG update several parents

我已经知道不可变 data-structures 在 Scala 中不能有循环。

但是,您如何处理 child 多个 parents 更新?

val child = Child("Tom")
val mother = Parent("Susi", child)
val father = Parent("Chuck", child)
val renamedChild = child.copy(name = "Tommy")
// how to update both references?

我没有深入研究 Zippers,但我认为它们只适用于简单的树而不是 DAG,对吗?

在不可变/持久数据结构中,你有结构共享,所以当你执行更新时,必须更新整体结构的一部分。对于像树这样的层次结构(如您的示例所示),这意味着您必须更新 top-to-bottom 从根目录到 child 的路径。这反过来又要求您了解您的 parents.

如果 motherfather "freely floating" 没有根,您也必须更新它们:

val mother1 = mother.copy(child = renamedChild)
val father1 = father.copy(child = renamedChild)

如果你有嵌套的数据结构并且你想避免手动执行 book-keeping(这很容易导致错误),你可以使用诸如 Lenses.[=15= 之类的方法]

如果你的结构是 directed-acyclic-graph,找到一个不可变的实现可能是一个挑战(我不知道持久的 DAG 结构——它可能是可行的,将 DAG 分解成一组树,但是我还没有遇到过任何这样的实现。


当然你总是可以有一个天真的(表现不佳)版本。

// set of vertices and map that points from children to parents!
type Graph[A] = (Set[A], Map[A, Set[A]])

def update[A](graph: Graph[A], before: A, now: A): Graph[A] = {
  val (vertices, edges) = graph
  val newV    = vertices - before + now
  val parents = edges.getOrElse(before, Set.empty)
  val newE    = if (parents.isEmpty) edges else edges - before + (now -> parents)
  (newV, newE)
}

val g1 = Set("Tom", "Susi", "Chuck") -> Map("Tom" -> Set("Susi", "Chuck"))
val g2 = update(g1, "Tom", "Tommy")