scala - Scala 中类型安全的完美二叉树

标签 scala types

我正在尝试实现类型安全 perfect binary tree在斯卡拉。换句话说,应该编译以下内容:

 Succ(Node(Leaf("a"), Leaf("b")))
 Node(
   Succ(Node(Leaf("a"), Leaf("b"))),
   Succ(Node(Leaf("c"), Leaf("d"))))

但以下情况不应该:

 Node(
   Succ(Node(Leaf("a"), Leaf("b"))),
   Leaf("c"))

我想出了下面的解决方案,可以满足上述要求,但可以欺骗编译器:

Node(
   Leaf("f"): PerfectBinaryTree,
   Succ(Node(Leaf("a"), Leaf("b"))): PerfectBinaryTree)

在 Scala 中是否有办法避免这种情况? 它与 Haskell 有什么不同(如果有的话)?

trait PerfectBinaryTree {
    type N <: PerfectBinaryTree
  }

  case class Succ[P <: PerfectBinaryTree](p: P) extends PerfectBinaryTree {
    type N = Succ[P]
  }

  class Leaf[T] private (t: T) extends PerfectBinaryTree {
    type N = Leaf[T]
  }

  object Leaf {
    def apply[T](t: T): Leaf[T] = new Leaf(t)
  }

  case class Node[A <: PerfectBinaryTree, B <: PerfectBinaryTree](l: A, r: B)(implicit evidence: A =:= B) extends PerfectBinaryTree {
    type N = A
  }

最佳答案

技巧(就像在 Haskell 中一样)是在类型变量 ( polymorphic recursion ) 内传递 Node

类的定义就变得非常简单

case class Node[+A](left: A, right: A);

sealed trait Tree[+A];
case class Succ[+A](subtree: Tree[Node[A]]) extends Tree[A];
case class Leaf[+A](value: A) extends Tree[A];

(当然你想添加折叠/遍历这样一棵树等的功能。)

然后,在创建值时,Succ 构造函数的数量决定了叶子需要多少个 Node。请注意,始终只有一个叶子,但它包含一个由给定数量的 Node 级别组成的二叉树:

val sample: Tree[String] =
 Succ(
  Succ(
    Leaf(
      Node(
        Node("a", "b"),
        Node("c", "d")
      )
    )
  )
);

关于scala - Scala 中类型安全的完美二叉树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33244138/

相关文章:

json - 如何在 Play 框架 v2.0 中呈现 JSON 响应(来自 GIT 的最新版本)

scala - 如何在 Scala 中创建时间戳序列

scala - 使用 DecisionTreeModel Spark ML 保存管道

haskell - 从 Yesod 提供 CSS 文档

scala - 在Maven项目中运行Scalatest时如何使用-D设置系统属性

scala - 在 twitter finagle 中使用客户端证书

scala - 将类型与收集一起使用

haskell 中不同元组的列表

nhibernate - 使用 Fluent NHibernate 进行继承映射

r - `levels<-`(这是什么魔法?