4

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

我的第一次尝试是创建一个 forInt和一个 for 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
  }

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

所以我的问题是 - 一次为 Long、Int 和 BigInt 执行此操作的(惯用的)Scala 方式是什么?


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

以下是在这里阅读一些关于“类型类”的结果(我仍然不完全觉得我 100% 理解)所以这就是结果(如果你的眼睛受伤了,请原谅我,我比较陌生斯卡拉)

  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 添加了“支持”,因为它看起来不太难)

4

1 回答 1

5

你所拥有的看起来非常接近。几点评论:

你想要的类型类是Integral,不是Numeric

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

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

  import integral._
于 2013-07-14T19:22:50.223 回答