如何在scala中将Int作为有序的参数化

use*_*074 18 scala

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

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

  def someOp(t: T) if(t < 3) ...
  ...
}
Run Code Online (Sandbox Code Playgroud)

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

val test = new Test[Int]()
Run Code Online (Sandbox Code Playgroud)

编译器抱怨如下:

类型参数[Test [Int]]不符合类Test的类型参数bounds [T <:Ordered [T]]

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

thS*_*oft 22

发生这种情况是因为Int它不是Ordered[Int](看这里的原因)的子类.

但是,存在一个隐式强制Int,RichInt它是一个子类Ordered[Int],但它不是为下界触发的.使用<%(视图边界)而不是考虑隐式强制:

class Test[T <% Ordered[T]]
Run Code Online (Sandbox Code Playgroud)

  • 在scala 2.11中看不见的视图边界,似乎? (3认同)

Rüd*_*ehn 11

您可以使用Ordering [T]类型类作为隐式参数.如果你想编写泛型max函数,它看起来像这样:

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

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

max(1,2) // gives 2
Run Code Online (Sandbox Code Playgroud)

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

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

max((1,2), (3,4)) // gives (3,4) because 3 is larger than 1
Run Code Online (Sandbox Code Playgroud)

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

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

max(1,2)(negativeIntOrdering) // gives 1
Run Code Online (Sandbox Code Playgroud)

因此基于类型的方法比基于继承的方法更灵活.这就是像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 
}
Run Code Online (Sandbox Code Playgroud)