Scala的Ordered
特征已被删除,因此我们必须使用Ordering
。我试图重写我的BST类以使用Ordering
并得到编译错误。任何人都可以解释我如何正确使用Ordering
和Nothing
。这是我的代码:
abstract sealed class Tree[+A: Ordering] {
def value: A
def left: Tree[A]
def right: Tree[A]
def isEmpty: Boolean
/**
* Time - O(1)
* Space - O(1)
*/
def mkTree(v: A, l: Tree[A] = Leaf, r: Tree[A] = Leaf): Tree[A] =
Branch(v, l, r)
/**
* Fails with message.
*/
def fail(s: String): Nothing =
throw new NoSuchElementException(s)
}
case object Leaf extends Tree[Nothing] {
def value: Nothing = fail("Empty tree.")
def left: Tree[Nothing] = fail("Empty tree.")
def right: Tree[Nothing] = fail("Empty tree.")
def isEmpty: Boolean = true
}
case class Branch[A: Ordering](value: A, left: Tree[A], right: Tree[A]) extends Tree[A] {
def isEmpty: Boolean = false
}
编译时我得到以下内容:
Tree.scala:21: error: No implicit Ordering defined for Nothing.
case object Leaf extends Tree[Nothing] {
^
one error found
我曾经把这个类写成abstract class Tree[+A <% Ordered[A]]
,但它运行良好。
答案 0 :(得分:3)
我认为问题与Ordering
和你设置树的方式不同。错误消息是不言自明的:你已经说过应该有一个类型参数的隐式排序,但是在Leaf
的情况下,你已经给它了类型参数Nothing
,这不是没有订购。
所以我要说每个Tree
订购的要求是不正确的。您需要做的就是从第一行中删除: Ordering
,因为您已经在Branch
中包含了该要求,它确实有意义。
您的mkTree
方法需要(implicit ord: Ordering[A])
参数,但我看不出此方法的用途 - 它看起来像属于伴随对象的工厂方法(它所做的,因为你只是按照Branch对象) - 所以我会删除它。
答案 1 :(得分:2)
Luigi是正确的,对于Tree类型,顺序没有意义。但是,如果使用Algebraic Data Type,这个要求会更加明显,设计会更清晰。它们使用类层次结构作为接口的一部分,因此它们比面向对象更具功能性(如Scala中的Option和List)。
然后直接使用case类来实例化它们(不需要mkTree函数),并使用模式匹配来检索它们。
例如:
sealed trait Tree[+A] {
def isEmpty: Boolean
}
case object Leaf extends Tree[Nothing] {
def isEmpty: Boolean = true
}
case class Branch[+A: Ordering](value: A, left: Tree[A] = Leaf, right: Tree[A] = Leaf) extends Tree[A] {
def isEmpty: Boolean = false
}
def depthFirstSearch[A: Ordering](tree: Tree[A], expected: A): Option[Branch[A]] = {
import Ordering.Implicits._
tree match {
case t @ Branch(value, _, _) if value == expected => Some(t)
case Branch(value, left, _) if value > expected => depthFirstSearch(left, expected)
case Branch(value, _, right) if value < expected => depthFirstSearch(right, expected)
case _ => None
}
}