在Scala的泛型中约束类型以接受任何类型的Int

时间:2015-01-22 16:04:21

标签: scala

我想写一个模糊的函数:

def doubleit[A](a: A): A = {a + a}

但我希望'A'代表任何一种Int,但不是任何东西。有没有办法让Scala知道我想要'A'的意思?

def doubleit[A <: Int](a: A): A = {a + a}

被编译器拒绝。

1 个答案:

答案 0 :(得分:5)

在普通的Scala中,您可以使用类型类Integral

scala> def doubleit[A : Integral](a: A): A = implicitly[Integral[A]].plus(a, a)
doubleit: [A](a: A)(implicit evidence$1: Integral[A])A

scala> doubleit(2)
res0: Int = 4

scala> doubleit(BigInt(4))
res1: scala.math.BigInt = 8

另一种可能的语法:

def doubleit[A](a: A)(implicit ev: Integral[A]): A = ev.plus(a, a)

ev是这些隐式参数的常用名称。

也可以使用+-等常规操作,而不是plusminus

def doubleit[A](a: A)(implicit ev: Integral[A]): A = {
  import ev._
  a + a
}

或根据@KChaloux的建议,事先从Integral.Implicits导入:

import Integral.Implicits._
def doubleit[A : Integral](a: A): A = a + a

如果您希望该功能不仅支持整数,还支持DoubleBigDecimal等,您可以使用Numeric代替Integral

import Numeric.Implcits._
def doubleit[A : Numeric](a: A): A = a + a

<强>解释

编写[A : Integral]使函数接收类型为Integral[A]的隐式参数。所有基本整数类型的含义已在Scala中定义,因此您可以直接使用IntBigInt。通过定义类型为Integral的新隐式变量并实现所有必要的方法,也可以定义新的Integral[NewIntegralType]类型。

implicitly[Integral[A]]的调用会返回Integral[A]的隐式实例,其中包含用于添加的方法plus,以及用于对积分执行其他操作的其他方法。