在 scala 中为 类 使用数字类型边界的正确方法
Proper way to use Numeric type bounds for classes in scala
一般问题:定义类型为 Numeric
的泛型 class 的正确方法是什么,最好不使用任何 implicit
在 Scala 2 中?
具体示例:考虑以下围绕整数序列构建的玩具class:
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
类型,因此无法解析 [= 的参数类型20=]。尝试在 class 定义或方法定义中声明 +(x: Numeric[T])
或使用 (implicit num: T => Numeric[T])
无济于事。
使 class 编译并按预期运行的唯一方法是使用 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
,即使它在 class 定义中被声明为 Numeric
?
- 有没有更好的方法来解决这个问题而不使用丑陋的样板
implicitly[Numeric[T]].plus
?
- 一般来说,我们可以避免
implicit
在 scala 中处理此类情况吗?
Why couldn't compiler resolve method plus for T, even though it is declared as Numeric in the class definition?
首先,因为 T
不是 Numeric
;相反,它有一个 Numeric
typeclass 的实例与之关联
其次,即使 T
是 Numeric
,它也不会有 +
方法;因为,这不是类型类的工作方式。
检查这个:https://gist.github.com/BalmungSan/c19557030181c0dc36533f3de7d7abf4
Is there any better way to solve this issue without use of ugly boilerplate implicitly[Numeric[T]].plus?
是的,只需导入扩展方法:import Numeric.Implicits._
在顶层或在 class
或方法内。
Could we, in general, avoid implicit's to handle such cases in scala?
[T: Numeric]
只是 (implicit ev: Numeric[T])
的糖语法,所以不,你无法避免 implicits
真的很好。
一般问题:定义类型为 Numeric
的泛型 class 的正确方法是什么,最好不使用任何 implicit
在 Scala 2 中?
具体示例:考虑以下围绕整数序列构建的玩具class:
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
类型,因此无法解析 [= 的参数类型20=]。尝试在 class 定义或方法定义中声明 +(x: Numeric[T])
或使用 (implicit num: T => Numeric[T])
无济于事。
使 class 编译并按预期运行的唯一方法是使用 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
,即使它在 class 定义中被声明为Numeric
? - 有没有更好的方法来解决这个问题而不使用丑陋的样板
implicitly[Numeric[T]].plus
? - 一般来说,我们可以避免
implicit
在 scala 中处理此类情况吗?
Why couldn't compiler resolve method plus for T, even though it is declared as Numeric in the class definition?
首先,因为 T
不是 Numeric
;相反,它有一个 Numeric
typeclass 的实例与之关联
其次,即使 T
是 Numeric
,它也不会有 +
方法;因为,这不是类型类的工作方式。
检查这个:https://gist.github.com/BalmungSan/c19557030181c0dc36533f3de7d7abf4
Is there any better way to solve this issue without use of ugly boilerplate implicitly[Numeric[T]].plus?
是的,只需导入扩展方法:import Numeric.Implicits._
在顶层或在 class
或方法内。
Could we, in general, avoid implicit's to handle such cases in scala?
[T: Numeric]
只是 (implicit ev: Numeric[T])
的糖语法,所以不,你无法避免 implicits
真的很好。