我正在尝试编写一个带数字的函数并将它们加在一起:
object Add {
def[A](a1: A, a2: A) = a1 + a2
}
我收到错误:
[error] found : A
[error] required: String
现在很明显scala没有Hindley-Milner类型推断,但你会期望有一些抽象类,比如说Number
,所有的基本操作。如果有我找不到它。
相反,我发现我应该使用类型类:
def add[A](a1: A, a2: A)(implicit n: Numeric[A]) = {
a1 + a2
}
不起作用......但是:
def add[A](a1: A, a2: A)(implicit n: Numeric[A]) = {
import n._
a1 + a2
}
是吗,现在这对我来说似乎并不特别干净。请告诉我有更好的方法!
甚至不使用常规类型类;
def add[A: Numeric](a1: A, a2: A) = {
a1 + a2
}
有效,我必须添加2行:
def add[A: Numeric](a1: A, a2: A) = {
val n = implicitly[Numeric[A]]
import n._
a1 + a2
}
我觉得我错过了一些基本的东西,因为它不应该这么难添加两个数字
更新
感谢答案,我发现可以做到以下几点:
import scala.math.Numeric._
import scala.math.Numeric.Implicits._
def add[A: Numeric](a1: A, a2: A) = {
a1 + a2
}
这就是我一直想做的事情。
答案 0 :(得分:5)
当您需要A
为数字的证据时,该证据知道如何对A
类型的元素采取行动。
def add[A](a1: A, a2: A)(implicit ev: Numeric[A]) = {
ev.plus(a1,a2)
}
使用更复杂的中缀符号需要额外的含义。
def add[A](a1: A, a2: A)(implicit ev: Numeric[A]) = {
import Numeric.Implicits._
a1 + a2
}
甚至不使用普通类型......
应该注意的是你所谓的“常规类型使用”
def add[A: Numeric](a1: A, a2: A) = {...
...实际上是由编译器重写成这样的......
def add[A](a1: A, a2: A)(implicit evidence$1 Numeric[A]) = {...
...除了编译器没有约束到任何特定的名称修改公式,因此您不能依赖具有可预测名称的隐式参数。因此implicitly
用于重新实现隐式参数。
答案 1 :(得分:1)
您也可以直接使用Numeric类型方法
def add[A](a1: A, a2: A)(implicit n: Numeric[A]) = {
n.plus(a1,a2)
}
或
def add[A: Numeric](a1: A, a2: A) = {
implicitly[Numeric[A]].plus(a1,a2)
}
为了使用中缀运算符,您需要一个隐式的范围来使用适当的方法将类型A转换为类。这就是我们需要导入类型类提供的隐含的原因。