一般问题:定义类型为Numeric
的泛型类的正确方法是什么,最好不要在Scala 2中使用任何implicit
?
具体示例:考虑以下围绕Integer序列构建的玩具类:
class NewList(val values: Seq[Int]) {
def +(x: Int): NewList = new NewList(values.map(_ + x))
}
val x = new NewList(List(1,2,3))
(x + 5).values // ---> List(6, 7, 8)
现在假设我们想使NewList
通用,围绕任何数字序列:
// Would not compile
class NewList[T: Numeric](val values: Seq[T]) {
def +(x: T): NewList = new NewList(values.map(_ + x))
}
由于某种奇怪的类型不匹配,上面的代码无法编译
cmd2.sc:2: type mismatch;
found : T
required: String
def +(x: T): NewList[T] = new NewList(values.map(_ + x))
^Compilation Failed
Compilation Failed
据我所知,这个编译错误显然意味着编译器无法将变量x: T
解析为Numeric
类型,因此无法解析plus
的参数类型。尝试在类定义或方法定义中声明+(x: Numeric[T])
或使用(implicit num: T => Numeric[T])
将没有帮助。
使类按预期编译和行为的唯一方法是使用implicitly[Numeric[T]]
:的plus
方法
class NewList[T: Numeric](val values: Seq[T]) {
def +(x: T): NewList[T] = new NewList(values.map(implicitly[Numeric[T]].plus(_, x)))
}
val x = new NewList(List(1,2,3))
(x + 5).values // ---> List(6, 7, 8)
- 为什么编译器不能为
T
解析方法plus
,即使它在类定义中被声明为Numeric
- 有没有更好的方法来解决这个问题,而不使用丑陋的样板
implicitly[Numeric[T]].plus
- 一般来说,我们可以避免
implicit
在scala中处理此类情况吗
为什么编译器不能解析t的方法加号,即使它在类定义中声明为Numeric?
首先,因为T
不是Numeric
;相反,它有一个Numeric
类型类的实例与其关联
其次,即使T
是Numeric
,它也不会有+
方法;因为,类型类不是这样工作的
检查此项:https://gist.github.com/BalmungSan/c19557030181c0dc36533f3de7d7abf4
有没有更好的方法来解决这个问题,而不使用隐式的丑陋样板[Numeric[T]].plus?
是的,只需在顶层或class
或方法内部导入扩展方法:import Numeric.Implicits._
。
我们通常可以避免隐式来处理scala中的此类情况吗?
[T: Numeric]
只是(implicit ev: Numeric[T])
的糖语法,所以不,您无法避免implicits
这很好,真的。