Scala 使用隐式将类型参数视为数字

Scala 使用隐式将类型参数视为数字,scala,Scala,我在以下多态函数定义方面遇到问题: scala> def foo[A](x : A, y : A)(implicit o : A => Numeric[A]) : A = x + y <console>:7: error: type mismatch; found : A required: String def foo[A](x : A, y : A)(implicit o : A => Numeric[A]) : A = x + y sc

我在以下多态函数定义方面遇到问题:

scala> def foo[A](x : A, y : A)(implicit o : A => Numeric[A]) : A = x + y
<console>:7: error: type mismatch;
 found   : A
 required: String
       def foo[A](x : A, y : A)(implicit o : A => Numeric[A]) : A = x + y
scala>def foo[A](x:A,y:A)(隐式o:A=>Numeric[A]):A=x+y
:7:错误:类型不匹配;
发现:A
必需:字符串
def foo[A](x:A,y:A)(隐式o:A=>数值[A]):A=x+y

我想指定类型参数
A
可以用作
数值
,但它不起作用。我做错了什么?

您需要的两个更改是,第一个
隐式
不应该是从
a
Numeric[a]
的函数,而只是
Numeric[a]
,第二个您需要导入
Numeric.Implicits
,以获得启用
+
的隐式
操作

import scala.math.Numeric.Implicits._

def foo[A](x : A, y : A)(implicit num: Numeric[A]) : A = x + y
如果没有导入,您必须将其编写为:

def foo[A](x : A, y : A)(implicit num: Numeric[A]) : A = num.plus(x,y)

Numeric[A]
通常是一个实例,用于访问类型
A
上的算术运算。它将包含
def plus(x:A,y:A):A
,而不是
def add(x:A):A
,后者将包含一些类型为A的
this

它类似于java的
比较器
(或scala的
排序
),它有一个
比较(to1,to2)
,而不是java的
可比
(scala的
排序
),它有一个
比较器(tother)
。这些类型,以及隐式可用的单例实现,通常在Haskell语言中的一个密切相关的特性之后被称为TypeClass

所以你不想把
A
转换成
Numeric[A]
,你只需要一个
Numeric[A]
。 你的签名应该是

def foo[A](x: A, y: A)(implicit numeric: Numeric[A])
这有一条捷径,那就是

def foo[A: Numeric](x: A, y: A)
在方法
foo
中,您可以执行
numeric.plus(x,y)
,但是如果
导入scala.math.numeric.\u
,您将获得一些魔力和更方便的
x+y


关于评论中的问题:自从使用scala(在V2.8上)编程以来,语言是否发生了变化

语法
[A:Numeric]
,称为
上下文绑定
,在该语言中引入较晚,我不是100%确定,但我相信它在2.8中不可用。但这只是一个
隐式数值[a]
参数的快捷方式,在2.8版中是可能的(
Numeric
在2.8版中是可用的,实际上是刚刚引入的),当时应该如上图所示使用。除此之外,没有语言变化

然而,在scala的早期,更常见的是使用“视图”,这意味着隐式转换,而不是类型类,也就是说,使用诸如
compariable
/
Ordered
,而不是
Comparator
/
Ordering

对于此类类型,通常使用上界
A有序[A]

过去有一个快捷方式,
[a Ordered[a]
),类型类是首选。原因有很多,例如:

  • 在隐式作用域中使用转换函数将充当隐式强制转换,这是非常危险的
  • TypeClass功能更强大。例如,您可以拥有
    Numeric[A]的实例
    即使你周围没有
    A
    的实例,也可以得到
    A
    类型的
    zero
    。如果你在一个列表上调用
    sum
    ,而列表是空的,那么
    Numeric
    仍然可用,你可以得到
    zero
    。如果
    Numeric
    A
    实现的东西,即使它是空的ade
    zero
    可用时,您将没有可调用的实例。另一个示例是,typeclass可以用作工厂,同样,当您没有构造类型的实例时(尚未),如中所示
引用Martin Odersky()的话:

上下文边界本质上是视图边界的替换 我们从一开始就应该做些什么,但我们并不清楚 当时


谢谢。当我模仿Scala book中编程的一段代码片段时,Typesafe是否更改了隐式的语法?该代码片段定义了一个函数,正如我在文章中所做的。在上面的回复中回答