【问题标题】:Scala's Ordering and NothingScala 的排序和无
【发布时间】:2013-09-02 22:15:29
【问题描述】:

Scala 的 Ordered 特性已被贬低,因此我们必须使用 Ordering。我试图重写我的 BST 类以使用 Ordering 并得到一个编译错误。谁能解释我如何正确使用OrderingNothing。这是我的代码:

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]],效果很好。

【问题讨论】:

    标签: scala implicit


    【解决方案1】:

    我认为问题不在于Ordering,而在于您设置树的方式。错误消息是不言自明的:您说过类型参数应该有一个隐式排序,但是在Leaf 的情况下,您已经给它类型参数Nothing,它没有订购。

    所以我想说每个Tree 都有一个排序的要求是不正确的。要解决这个问题,您需要做的就是从第一行中删除 : Ordering,因为您已经在 Branch 中包含了该要求,它确实有意义。

    您的 mkTree 方法需要一个 (implicit ord: Ordering[A]) 参数,但我看不出这个方法有什么用途 - 它看起来像一个属于伴随对象的工厂方法(它确实如此,因为你只是推迟到 Branch 对象) - 所以我会删除它。

    【讨论】:

      【解决方案2】:

      Luigi 是正确的,该顺序对于 Tree 类型没有意义。然而,如果使用Algebraic Data Type,这个要求会更明显,并且设计会更简洁。它们使用类层次结构作为接口的一部分,因此它们比面向对象(如 Scala 中的 Option 和 List)更具功能性。

      然后您直接使用案例类来实例化它们(不需要 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
        }
      }
      

      【讨论】:

      • 我同意 valueleftright 不需要在 Tree 特征中。我认为 OP 正在遵循 List 的实现,详见 Scala 编程第 22 章。 headtailList 中定义,而不仅仅是在 :: 中。不知道为什么,但我怀疑这是具有较弱类型系统的函数式语言的遗留问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-05
      • 2014-06-28
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      相关资源
      最近更新 更多