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