Scala相当于Haskel Number

use*_*470 0 scala typeclass

这可能是之前被问到的,我找到了一些旧的回答,但我发现很难接受它们.

我正在尝试编写一个函数,它接受数字并将它们加在一起:

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)

这就是我一直想做的事情.

jwv*_*wvh 5

当您需要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用于重新实现隐式参数.