为什么以下Scala实验性代码无法工作?

3
我正在尝试定义一个通用的加法函数,用于数字数值:
def add[A](x:A, y:A): A = {
  x + y
}


控制台:16:错误:类型不匹配; 发现:A 需要:String x + y ^

编译器在抱怨什么? 我在谷歌上搜索到的一些内容目前并不太让我理解。


你已经明确告诉编译器,你有一个方法,它接受两个参数,这些参数的类型你一无所知(除了它们是相同的类型)。既然你明确告诉编译器你对这些类型一无所知,那么你也不能知道它们是否有一个 + 方法。 - Jörg W Mittag
1
可能是Scala中的类型参数的重复问题。 - Jörg W Mittag
2个回答

10
由于您在定义A时没有指定边界和额外信息,它可以是任何类型。然而,并非所有的Scala类型都具有+方法,所以无法编译。
错误消息是由编译器尝试将x隐式转换为字符串(因为String具有+方法,并且每种类型都可以使用toString转换为字符串)导致的,但失败了,因为y不是一个字符串。
要为所有数字类型创建方法,您可以使用Numeric类型:
def add[A](x:A, y:A)(implicit n: Numeric[A]): A = {
  n.plus(x, y)
}

add(1, 3)
add(1.4, 3.5)

编辑:或者等价的语法:

def add[A: Numeric](x:A, y:A): A = {
  implicitly[Numeric[A]].plus(x, y)
}

编译器不能在实例化之前决定,还是我在 Scala 领域说了些无聊的话。因此,我相信你建议忘记其他编程语言处理泛型编程的内容。 - user1206899
1
根据定义,编译器在编译时运行(在程序运行之前),这意味着实例化不在考虑范围内(它只发生在运行时)。在Scala中,就像在任何其他强类型语言中一样,编译器验证类型及其方法的正确性,以便您在运行时不会遇到这些错误。 - Tzach Zohar

2
为了能够像这样做,编译器需要知道A有一个方法。
def +(a: A): A

理想情况下,您希望做的事情是这样的:
def add[A :< Numeric](x:A, y:A): A = { ... 

但是你不能这样做,因为在Scala中的数字类型没有共同的超类型(它们扩展AnyVal)。这里有一个相关的问题,请点击这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接