使用递归对类型Ordering [Any]的隐式扩展进行分歧

时间:2016-07-12 16:40:59

标签: scala

我正在尝试在Scala中实现BST。我想通过'+'运算符将节点添加到二叉树。但是我在编译期间遇到两个错误

Error:(39, 46) diverging implicit expansion for type Ordering[Any]
    starting with method orderingToOrdered in object Ordered
    def +[A: Ordering](v: A) : Tree[Any] = add(this, v)

Error:(39, 46) not enough arguments for method add: (implicit evidence$1: Ordering[Any])A$A47.this.Tree[Any].
Unspecified value parameter evidence$1.
  def +[A: Ordering](v: A) : Tree[Any] = add(this, v)

这是代码。

sealed trait Tree[+A]{
  def add[A: Ordering](tree: Tree[A], v: A) : Tree[A] = tree match {
    case EmptyTree => Node(EmptyTree, v, EmptyTree)
    case Node(l, x, r) => {
      if(x.compare(v) == 1)
        Node(add(l, v), x, r)
      else
        Node(l, x, add (r, v))
    }
  }

  def +[A: Ordering](v: A) : Tree[Any] = add(this, v)
}

有人可以帮助我并说出错误吗?

1 个答案:

答案 0 :(得分:1)

我认为问题是运营商+的界面。

def add[A: Ordering](tree: Tree[A], v: A) : Tree[A]

add函数接受Tree[A]并返回Tree[A],其中A受类型类Ordering约束。这里没有错(但最好在Tree)的伴随对象中定义它。

def +[A: Ordering](v: A) : Tree[Any] = add(this, v)

+函数接受tree类型的值(您假设此add的{​​{1}}参数为this)由类型类A约束。

这里的第一个问题是,您返回Ordering。我假设你的意思是Tree[Any]

第二个问题是,函数Tree[A]中的A +所指的类型参数A。所以你可能意味着:

this

如果这不是您想要的,则必须通过类型类sealed abstract class Tree[+A: Ordering] { ... def +(v: A) : Tree[A] = add(this, v) } 约束A函数中的+

Ordering

在这种情况下,sealed trait Tree[A] { ... def +(v: A)(implicit ev: Ordering[A]): Tree[A] = add(this, v) } 可能不再是协变,因为它发生在一个不变的位置。

修改:如下所述,还有机会在函数A中引入新类型B。整体代码可能如下所示:

+

第二次编辑:在上面的示例中,有必要引入超类型而不是子类型object Tree { def add[A](tree: Tree[A], v: A)(implicit ev: Ordering[A]): Tree[A] = ... } sealed trait Tree[+A] { def +[B >: A](v: B)(implicit ev: Ordering[B]): Tree[B] = Tree.add(this, v) } ... implementation of trait Tree ,因为函数B需要类型类Tree.add 1}} - 我们无法提供。

以下内容毫无意义,因为它只能证明Ordering[A]类型的值可以被排序。

B

这甚至都没有编译,因为def +[B <: A](v: B)(implicit ev: Ordering[B]): Tree[B] = ??? 发生在一个不变的位置。

A

为了实现def +[B <: A](v: B)(implicit ev: Ordering[A]): Tree[B] = ??? 不会出现在不变位置并且为了证明类型A的值以及类型B的值可以被排序,我们必须介绍A作为超级类型。