Scala 应用于Int和Long的泛型隐式类

Scala 应用于Int和Long的泛型隐式类,scala,Scala,我想通过添加一些助手方法为Scala中的自然数创建一个“皮条客我的类型” 我的第一次尝试是为Int创建一个,为Long创建一个(以后可能还会为BigInt创建一个) 当然,代码完全相同,不太干,而且“感觉”不对 所以我的问题是-什么是(惯用的)Scala方法可以同时长时间、Int和BigInt执行此操作? p、 这是我到目前为止所尝试的,它有点有效,但我很确定它不是惯用的,并且有很多问题 下面是读了一点关于“类型类”(我仍然不完全认为我100%理解)的结果(如果你的眼睛受伤了,请原谅,我对Sc

我想通过添加一些助手方法为Scala中的自然数创建一个“皮条客我的类型”

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

当然,代码完全相同,不太干,而且“感觉”不对

所以我的问题是-什么是(惯用的)Scala方法可以同时长时间、Int和BigInt执行此操作?


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

下面是读了一点关于“类型类”(我仍然不完全认为我100%理解)的结果(如果你的眼睛受伤了,请原谅,我对Scala比较陌生)


(我添加了对非Int的“支持”,只要它看起来不太难)

您所拥有的看起来非常接近。几点意见:

您想要的类型类是
整数
,而不是
数值

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

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

  import integral._

请记住,与原语相比,任何带有
数值的
都会非常慢。有关如何快速执行此操作,请参见spire。这可不是什么小事。(谷歌scala spire。)谢谢,我想在这种情况下,DRY可以离开窗口,我可以简单地拥有一个
trait SuperNum
,它有
squared:Numeric
等,并用
squared:Long
覆盖它,等很久吗?谢谢!这种方法有运行时性能价格标签吗?是的,据我所知。因为要计算
4.squared
,它必须将
int
框为
int
,将其包装在一个
SuperNumber
(有两个字段)中,然后用
IntegralOps
再次包装以进行乘法。这是三个对象实例化。现在,在真正的JVM上,这样做的实际成本是多少?我不能说(永远不要在没有基准的情况下推测性能…)
  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
          }
        }
      }
    }
  }
implicit class SuperNumber[A](i: A)(implicit integral: Integral[A]) {

  import integral._