适用于Int和Long的通用隐式类

时间:2013-07-14 19:07:03

标签: scala

我想通过添加一些辅助方法为Scala中的自然数创建一个“pimp my type”。

我的第一次尝试是为Int创建一个,为Long创建一个(后来也可能为BigInt创建一个)

  implicit class SuperInt(n:Int) {
    def square = n * n
    def pow(m: Int) = math.pow(n,m)
    def **(m: Int) = pow(m)
    def sqrt = math.sqrt(n)
    def isEven = dividesBy(2)
    def isOdd = !isEven
    def dividesBy(m:Int) = n % m == 0
  }

  implicit class SuperLong(n:Long) {
    def square = n * n
    def pow(m: Int) = math.pow(n,m)
    def **(m: Int) = pow(m)
    def sqrt = math.sqrt(n)
    def isEven = dividesBy(2)
    def isOdd = !isEven
    def dividesBy(m:Int) = n % m == 0
  }

当然完全相同的代码,不是太干,也不“感觉”正确。

所以我的问题是 - 什么是(惯用的)Scala方式一次性为Long,Int和BigInt做这个?


P.S。这是我到目前为止所尝试的,它有点工作,但我很确定它不是惯用的,并且有很多问题。

以下是关于“类型类”here的阅读结果(我仍然没有完全感觉到我100%理解)所以这就是结果(如果你的眼睛受伤了,请原谅我,我对Scala相对较新)

  implicit class SuperNumber[A : Numeric](i: A) {
    import Numeric.Implicits._
    def squared: A = i * i
    def pow(m: Int) = math.pow(i.toDouble(),m)
    def **(m: Int) = pow(m)
    def sqrt = math.sqrt(i.toDouble())
    def isEven = dividesBy(2)
    def isOdd = !isEven
    def dividesBy(m:Int) = {
      i match {
        case n @ (_:Int | _:Long) => n.toLong() % m == 0
        case other => {
          val asDouble = other.toDouble()
          val asLong = other.toLong()
          if (asDouble == asLong) {
            asLong % m == 0
          } else {
            false
          }
        }
      }
    }
  }

(我为非Int和Long添加了“支持”,因为它似乎并不太难)

1 个答案:

答案 0 :(得分:5)

你看起来非常接近。一些评论:

您想要的类型类是Integral,而不是Numeric

不是将上下文绑定为[A: Integral],而是在构造函数上放置一个隐式参数,这样就可以从该对象中导入mkNumericOps

implicit class SuperNumber[A](i: A)(implicit integral: Integral[A]) {

  import integral._