如何在Scala中将Int参数化为Ordered

时间:2013-10-15 15:31:51

标签: scala

我有一个参数化类型的类,我想做比较运算符。我认为我需要使用Ordered trait来实现这一点,但编译器不喜欢我使用它。所以说我有以下课程:

class Test[T <: Ordered[T]] {

  def someOp(t: T) if(t < 3) ...
  ...
}

但是,如果我尝试按如下方式使用此类:

val test = new Test[Int]()

编译器抱怨如下:

  

类型参数[Test [Int]]不符合类Test的类型   参数边界[T&lt ;:Ordered [T]]

有人可以向我解释我在这里做错了吗?

2 个答案:

答案 0 :(得分:20)

这是因为Int不是Ordered[Int]的子类(请参阅here为什么)。

但是,从IntRichInt的隐式强制是Ordered[Int]的子类,但它不会触发下限。使用<%(查看边界)代替which will consider implicit coercions

class Test[T <% Ordered[T]]

答案 1 :(得分:10)

您可以使用Ordering[T]类型类作为隐式参数。如果你想编写一个通用的max函数,它将如下所示:

def max[T](a:T, b:T)(implicit ordering:Ordering[T]) = { 
  if(ordering.gt(a,b)) a else b 
}

对于原始数据类型,如Int,Float,...,范围内有一个隐式的Ordering [T],以便您可以按预期使用它。

max(1,2) // gives 2

对于实现Ordered [T]的所有类型,还有一个隐式提供Ordering [T]。

范围内还有各种方法可以组合排序。例如,如果你有一个N元组,其中每个元素都有一个Ordering [T],那么自动存在一个元组类型的排序。

max((1,2), (3,4)) // gives (3,4) because 3 is larger than 1

如果您对任何隐式提供的排序不满意,您可以自己编写并明确传递它,或者甚至将其作为隐式val 在范围内获取。像这样:

val negativeIntOrdering = new Ordering[Int] { 
  def compare(a:Int,b:Int) = b - a 
}

max(1,2)(negativeIntOrdering) // gives 1

因此,基于类型的方法比基于继承的方法更灵活。这就是像spire这样的数学库广泛使用它的原因。

上面代码不太好的一件事是你必须使用lt方法而不是运算符。但也有一个解决方案。 Ordering有一个名为mkOrderingOps的隐式方法,为T提供运算符。你只需要通过导入orders._来获取它,如下所示:

def max[T](a:T, b:T)(implicit ordering:Ordering[T]) = { 
  import ordering._; 
  if(a>b) a else b 
}