使用带有PriorityQueue(Scala)的隐式有序的麻烦

时间:2013-02-13 04:01:29

标签: scala priority-queue implicits

我正在尝试创建一个包含PriorityQueue的数据结构。我成功地制作了它的非泛型版本。我可以告诉它有效,因为它解决了A.I.我有问题。
以下是它的片段:

class ProntoPriorityQueue { //TODO make generic

implicit def orderedNode(node: Node): Ordered[Node] = new Ordered[Node] {
   def compare(other: Node) = node.compare(other)
}

val hashSet = new HashSet[Node]
val priorityQueue = new PriorityQueue[Node]()
...

我试图让它变得通用,但是如果我使用这个版本它就会停止解决问题:

class PQ[T <% Ordered[T]] {
//[T]()(implicit val ord: T => Ordered[T]) {
//[T]()(implicit val ord: Ordering[T] {

val hashSet = new HashSet[T]
val priorityQueue = new PriorityQueue[T]
...

我也尝试过注释而不是使用[T <% Ordered[T]]

以下是调用PQ的代码:

//the following def is commented out while using ProntoPriorityQueue
implicit def orderedNode(node: Node): Ordered[Node] = new Ordered[Node] {
     def compare(other: Node) = node.compare(other)
} //I've also tried making this return an Ordering[Node]

val frontier = new PQ[Node] //new ProntoPriorityQueue
//have also tried (not together): 
val frontier = new PQ[Node]()(orderedNode)

我也尝试将隐式def移动到Node对象(并导入它),但基本上是同样的问题。

我在通用版本中做错了什么?我应该把隐含的地方放在哪里?


解决方案 问题不在于我的隐含定义。问题是隐式排序是由Setfor(...) yield(...)语句中自动生成的。这导致了一个问题,即屈服集只包含一个状态。

2 个答案:

答案 0 :(得分:1)

简单地在OrderingNode)上定义Ordering[Node]并使用已经通用的Scala PriorityQueue有什么问题?

作为一般规则,最好使用Ordering[T]而不是T <: Ordered[T]T <% Ordered[T]。从概念上讲,Ordered[T]是类型本身的内在(继承或实现)属性。值得注意的是,类型只能以这种方式定义一个内部排序关系。 Ordering[T]是排序关系的外部规范。可以有任意数量的不同Ordering[T]

另外,如果你还没有意识到,你应该知道T <: UT <% U之间的区别在于前者只包含名义子类型关系(实际继承),后者还包括隐式转换的应用,产生符合类型约束的值。

因此,如果您要使用Node <% Ordered[Node]并且您没有在类中定义compare方法,则每次需要进行比较时都会应用隐式转换< / em>的。此外,如果您的类型拥有自己的compare,则隐式转换将永远不会应用,您将无法使用“内置”排序。

<强>附录

我将基于一个类给出一些示例,将其称为CIString,简单地封装一个String并实现排序为case-invariant。

/* Here's how it would be with direct implementation of `Ordered` */

class   CIString1(val s: String)
extends Ordered[CIString1]
{
  private val lowerS = s.toLowerCase

  def compare(other: CIString1) = lowerS.compareTo(other.lowerS)
}

/* An uninteresting, empty ordered set of CIString1
    (fails without the `extends` clause) */
val os1 = TreeSet[CIString1]()


/* Here's how it would look with ordering external to `CIString2`
    using an implicit conversion to `Ordered` */

class CIString2(val s: String) {
  val lowerS = s.toLowerCase
}

class CIString2O(ciS: CIString2)
extends Ordered[CIString2]
{
  def compare(other: CIString2) = ciS.lowerS.compareTo(other.lowerS)
}

implicit def cis2ciso(ciS: CIString2) = new CIString2O(ciS)

/* An uninteresting, empty ordered set of CIString2
    (fails without the implicit conversion) */
val os2 = TreeSet[CIString2]()


/* Here's how it would look with ordering external to `CIString3`
    using an `Ordering` */

class CIString3(val s: String) {
  val lowerS = s.toLowerCase
}

/* The implicit object could be replaced by
    a class and an implicit val of that class */
implicit
object  CIString3Ordering
extends Ordering[CIString3]
{
  def compare(a: CIString3, b: CIString3): Int = a.lowerS.compareTo(b.lowerS)
}

/* An uninteresting, empty ordered set of CIString3
    (fails without the implicit object) */
val os3 = TreeSet[CIString3]()

答案 1 :(得分:0)

嗯,一个可能的问题是,您的Ordered[Node] 不是 Node

implicit def orderedNode(node: Node): Ordered[Node] = new Ordered[Node] {
  def compare(other: Node) = node.compare(other)
}

我会尝试使用Ordering[Node]代替,您说您尝试了但是没有更多信息。 PQ将被声明为PQ[T : Ordering]