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

Sal*_*ley 1 scala

我想写一个函数模糊地像:

def doubleit[A](a: A): A = {a + a}
Run Code Online (Sandbox Code Playgroud)

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

def doubleit[A <: Int](a: A): A = {a + a}
Run Code Online (Sandbox Code Playgroud)

被编译器拒绝.

Kol*_*mar 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
Run Code Online (Sandbox Code Playgroud)

另一种可能的语法

def doubleit[A](a: A)(implicit ev: Integral[A]): A = ev.plus(a, a)
Run Code Online (Sandbox Code Playgroud)

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

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

def doubleit[A](a: A)(implicit ev: Integral[A]): A = {
  import ev._
  a + a
}
Run Code Online (Sandbox Code Playgroud)

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

import Integral.Implicits._
def doubleit[A : Integral](a: A): A = a + a
Run Code Online (Sandbox Code Playgroud)

如果您希望该函数不仅支持整数,还支持Doubles,BigDecimals等,您可以使用Numeric而不是Integral:

import Numeric.Implcits._
def doubleit[A : Numeric](a: A): A = a + a
Run Code Online (Sandbox Code Playgroud)

说明:

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

implicitly[Integral[A]]返回此隐式实例的调用Integral[A]具有添加方法plus,以及其他用于对积分执行其他操作的方法.