【问题标题】:Comparisons with Scala's Numeric types?与 Scala 的数值类型比较?
【发布时间】:2011-11-17 15:03:09
【问题描述】:

如何创建一个类来对 Scala 中的任何数字类型进行数学比较?

一个明显的方法:

import math.Numeric.Implicits._

class Ops[T : Numeric] {
    def add(a: T, b: T) = a + b
    def gt(a: T, b: T) = a > b
}

让我赚到这个……

Ops.scala:7: value > is not a member of type parameter T

嗯...我们可以用数字类型做数学,但我们不能比较它们?

所以我们也可以说TOrdered[T]...

class Ops[T <: Ordered[T] : Numeric] {
    def add(a: T, b: T) = a + b
    def gt(a: T, b: T) = a > b
}

编译。但是尝试使用它?

new Ops[Int].gt(1, 2)

我得到...

Ops.scala:13: type arguments [Int] do not conform to class Ops's type parameter bounds [T <: Ordered[T]]

那么我怎样才能对一些既是有序又是数字的类型进行操作呢?

【问题讨论】:

    标签: scala math numeric


    【解决方案1】:
    scala> import Ordering.Implicits._
    import Ordering.Implicits._
    
    scala> import Numeric.Implicits._
    import Numeric.Implicits._
    
    scala> class Ops[T : Numeric] {
         |   def add(a: T, b: T) = a + b
         |   def gt(a: T, b: T) = a > b
         | }
    defined class Ops
    
    scala> new Ops[Int].gt(12, 34)
    res302: Boolean = false
    

    【讨论】:

    • 很好,与本地导入 numeric.mkXXXOps 相比,不知道这种全局导入。将使用它。
    • Numeric 扩展Ordering,因此要求Ordering 上下文边界是多余的! T : Numeric 就够了。
    • @Sciss 好点!是我说应该close看看 API 的吗?!还没有仔细看Numeric &lt;: Ordering...
    • 我猜测数字必须以某种方式排序(这就是为什么我在下面的评论中如此困惑的原因)。我也不知道排序隐含。 (刚刚开始。)
    【解决方案2】:

    您必须导入mkNumericOps 和/或mkOrderingOps

    val num = implicitly[Numeric[T]]
    

    class Ops[T](implicit num: Numeric[T]) 
    

    然后:

    import num.{mkNumericOps,mkOrderingOps}
    

    现在您可以与它们进行比较和计算。 也许这可以帮助您解决问题的第一部分。

    顺便说一句:Ordered 和 Numeric 的工作方式是这样的:

    class Ops[T: Ordered: Numeric]
    

    【讨论】:

    • 那就是T : Ordering : Numeric(或T &lt;: Ordered : NumericT &lt;% Ordered : Numeric
    • @Tim 我自己也遇到了你的问题,并认为必须有一种方法不会那么笨拙地调用gt。所以我看了一下 API,有一个神秘的 mkOrderingOps... 总是仔细看看 API!
    • 应该说你不需要TOrdered 才能工作。所以有T : Numeric就足够了。正如 didierd 指出的那样,Ordered 将用作此处绑定的视图 (T &lt;% Ordered),并且作为上下文绑定没有意义。在性能方面,使用OrderingOrdering.Implicits._ 应该是更好的选择,因为使用Ordered,您的值会被不必要地装箱。
    • 是的,我也尝试过使用gt,但甚至可以让那个工作。正如我在下面所说的那样,我只是加快速度,对于import num.{mkNumericOps,mkOrderingOps} 的工作原理仍然有些困惑。那如何在 other 变量上导入 infix 运算符?
    • @Tim: mkNumericOps 是从N 类型到Op 类型的隐式转换(其中N 是一些Numeric 类型)。此类Op 包含中缀数字运算符。换句话说,您的代码中的a + b 脱糖为mkNumericOps(a).+(b)
    猜你喜欢
    • 2012-11-16
    • 1970-01-01
    • 1970-01-01
    • 2010-11-03
    • 1970-01-01
    • 2021-07-31
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多