我在使用以下多态函数定义时遇到了问题:
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
我想指定类型参数A
可以用作Numeric
,但它不起作用。我做错了什么?
答案 0 :(得分:4)
Numeric[A]
通常是单个实例,可以访问类型A
上的算术运算。它将包含def plus(x: A, y: A): A
,而不是def add(x: A): A
,其中包含this
类型的Comparator
。
类似于java的Ordering
(或scala的Compare(T o1, T o2)
),它有Comparable
,而不是java Ordered
(scala的CompareTo(T other)
)一个A
。在Haskell语言中密切相关的特征之后,具有隐式可用的单例实现的这种类型通常被称为类型类。
因此,您不希望将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)
中,您可以执行import scala.math.Numeric._
,但如果您x + y
,则会获得一些魔力,而且更方便[A: Numeric]
。
关于评论中的问题:自scala编程以来是否有语言更改(第2.8版)?
语法context bound
,称为implicit Numeric[A]
,已在语言后期引入,我不是百分百肯定,但我相信它在2.8中不可用。但这只是Numeric
参数的快捷方式,这可能是2.8(Comparable
可用 - 实际上只是在2.8中引入),并且应该如上所示使用。除此之外,没有语言变化。
然而,在scala的早期,使用“views”更常见,这意味着隐式转换,而不是类型,即使用Ordered
/ Comparator
等类型比Ordering
/ Numeric
/ A <: Ordered[A]
。
对于此类型,通常使用上限Ordered
。但是,这可能有点过于严格,因为只有实现者有远见才能实现A
时它才会起作用。你可以解决这个问题,但要求implicit A => Ordered[A]
可以转换为有序[A],所以[A <% Ordered[A]]
。
曾经有一个快捷方式,implicit A => Ordered[A]
,称为视图绑定。但是,它已被弃用,虽然仍然可以查看视图(Numeric[A]
),但更喜欢类型类。这有很多原因,例如:
A
的实例,也可以拥有zero
的实例,因此请获取A
类型的sum
。如果您在列表中拨打Numeric
并且列表为空,则zero
仍然可用,您可以获得Numeric
。如果A
由zero
实现,即使它jArrayFull
可用,您也没有实例可以调用它。另一个例子,类型类可以用作工厂,再次当你没有构造类型的实例时(如)this answer中所示。引用Martin Odersky(discussing deprecation):
上下文边界本质上是视图边界的替代。它的 从一开始我们应该做些什么,但我们不知道更好 那时候
答案 1 :(得分:2)
您需要做的两项更改是,首先 implicit
不应该是A
到Numeric[A]
的功能,而只是Numeric[A]
, second ,您需要导入Numeric.Implicits
以获取启用Ops
的隐式+
。
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)