【问题标题】:How to paramaterize Int as Ordered in scala如何在scala中将Int参数化为Ordered
【发布时间】:2013-10-23 11:51:46
【问题描述】:

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

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

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

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

val test = new Test[Int]()

编译器报错如下:

类型参数 [Test[Int]] 不符合类 Test 的类型 参数范围[T <: ordered>

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

【问题讨论】:

  • 在这种情况下使用Ordering 而不是Ordered 通常是更好的方法。

标签: scala


【解决方案1】:

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

但是,从 IntRichInt 的隐式强制转换是 Ordered[Int] 的子类,但不会针对下限触发。使用&lt;%(视图边界)代替which will consider implicit coercions

class Test[T <% Ordered[T]]

【讨论】:

  • 似乎在 scala 2.11 中已弃用视图边界?
【解决方案2】:

您可以使用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],则该元组类型会自动存在一个 Ordering。

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 提供运算符。您只需通过导入 ordering._ 将其置于范围内,如下所示:

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

【讨论】:

  • 救了我的 b**t:我正要完全放弃 ordered/ordering 之类的东西
猜你喜欢
  • 1970-01-01
  • 2017-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-18
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
相关资源
最近更新 更多