一般问题:定义使用类型为数字
的通用类的正确方法,理想情况下,不使用Scala 2中的任何隐式
?
特定示例:考虑围绕整数序列构建的以下玩具类:
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
generic,围绕任何数字序列缠绕:
// 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> numeric
类型,因此无法解析 plus
的参数类型。尝试声明+(x:numeric [t])
或使用(隐式num:t => numeric [t])
在类别定义或方法定义中都不会帮助。
进行类编译和行为预期的唯一方法是使用 plus
的方法> 隐式[numeric [t]]
:
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
,即使在类别定义中将其声明为数字
?
- 是否有更好的方法来解决此问题,而无需使用丑陋的样板
隐式[numeric [t]]。加上
?
- 通常,我们可以避免
隐式
在Scala中处理此类案例吗?
General question: What is the proper way to define a generic class typed with a type which is Numeric
, ideally without using any implicit
in Scala 2?
Specific example: consider the following toy class which is built around Integer sequence:
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)
Now suppose we want to make NewList
generic, wrapping around any numeric sequence:
// Would not compile
class NewList[T: Numeric](val values: Seq[T]) {
def +(x: T): NewList = new NewList(values.map(_ + x))
}
The code above would not compile due to some weird type mismatch
cmd2.sc:2: type mismatch;
found : T
required: String
def +(x: T): NewList[T] = new NewList(values.map(_ + x))
^Compilation Failed
Compilation Failed
As far as I understand, this compilation error apparently means, that compiler could not resolve variable x: T
to be of a Numeric
type, and thus could not resolve type of arguments of plus
. Trying to declare +(x: Numeric[T])
or using (implicit num: T => Numeric[T])
either in class definition or method definition would not help.
The only way to make the class compile and behave as expected is to use plus
method of implicitly[Numeric[T]]
:
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)
- Why couldn't compiler resolve method
plus
for T
, even though it is declared as Numeric
in the class definition?
- Is there any better way to solve this issue without use of ugly boilerplate
implicitly[Numeric[T]].plus
?
- Could we, in general, avoid
implicit
's to handle such cases in scala?
发布评论
评论(1)
首先,因为
t
不是数字
;相反,它具有数字
typeclass 与之关联的实例其次,即使
t
是数字
,它也不具有+
方法;因为同样,这不是类型的工作方式。检查以下内容:
是的,只需导入扩展方法:
import numeric.implicits ._
在顶级或class
或方法或方法内。[t:numeric]
只是的糖语法(隐式ev:numeric [t])
所以不,您无法避免隐含
很好,真的。
First, because
T
IS NOT aNumeric
; rather it has an instance ofNumeric
typeclass associated with itSecond, even if
T
would be aNumeric
, it would not have a+
method; because, again, that is not how typeclasses work.Check this: https://gist.github.com/BalmungSan/c19557030181c0dc36533f3de7d7abf4
Yes, just import the extension methods:
import Numeric.Implicits._
either at the top level or inside theclass
or the method.[T: Numeric]
is just sugar syntax for(implicit ev: Numeric[T])
so no, you can't avoidimplicits
Which is fine, really.