如何在 Scala 中实现通用数学函数
我刚刚开始使用 Scala,一些我认为应该很容易的事情却很难弄清楚。我正在尝试实现以下函数:
def square(x:Int):Int = { x * x }
这工作得很好,但如果我想尝试使这个函数适用于任何类型我希望能够执行以下操作:
def square[T <: Number](x : T):T = { x * x }
这抱怨并说:错误:值* 不是类型参数 T 的成员
我需要为此实现一个特征吗?
I'm just getting started with Scala and something which I think should be easy is hard to figure out. I am trying to implement the following function:
def square(x:Int):Int = { x * x }
This works just fine, but if I want to try to make this function work for any kind of number I would like to be able to do the following:
def square[T <: Number](x : T):T = { x * x }
This complains and says: error: value * is not a member of type parameter T
Do I need to implement a trait for this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是我在 Stack Overflow 或有关 Scala 的第一个问题之一。问题在于 Scala 保持了与 Java 的兼容性,这意味着它的基本数字类型与 Java 的基元相同。
问题的出现是因为 Java 基元不是类,因此没有允许“数字”超类型的类层次结构。
更简单地说,Java 以及 Scala 在
Double
的+
和Int
之间看不到任何共同点> 的+
。Scala 最终解决此限制的方法是在所谓的类型类中使用
Numeric
及其子类Fractional
和Integral
模式。基本上,您可以这样使用它:或者,如果您不需要任何数字运算,但您调用的方法需要,则可以使用上下文绑定语法进行类型声明:
有关详细信息,请参阅我自己问题中的答案。
That was one of my first questions in Stack Overflow or about Scala. The problem is that Scala maintains compatibility with Java, and that means its basic numeric types are equivalent to Java's primitives.
The problem arises in that Java primitives are not classes, and, therefore, do not have a class hierarchy which would allow a "numeric" supertype.
To put it more plainly, Java, and, therefore, Scala, does not see any common grounds between a
Double
's+
and a anInt
's+
.The way Scala finally got around this restriction was by using
Numeric
, and its subclassesFractional
andIntegral
, in the so-called typeclass pattern. Basically, you use it like this:Or, if you do not need any of the numeric operations but the methods you call do, you can use the context bound syntax for type declaration:
For more information, see the answers in my own question.
您可以将 Square 定义为:
此方法的优点是它适用于任何隐式转换为 Numeric[T] 的类型 T(即 Int、Float、Double、Char、BigInt、.. .,或您为其提供隐式转换的任何类型)。
编辑:
不幸的是,如果您尝试类似
List(1,2,3).map(square)
的操作,您会遇到麻烦(具体来说,您会收到类似“无法找到隐式值”的编译错误对于 Numeric[T] 类型的证据参数”。为了避免这个问题,您可以重载square
以返回一个函数:希望对类型推断器有更好理解的人能够解释为什么会这样。
或者,正如 Derek Williams 在 scala 用户邮件列表线程。
You can define
square
as:This approach has the advantage that it will work for any type T that has an implicit conversion to Numeric[T] (i.e. Int, Float, Double, Char, BigInt, ..., or any type for which you supply an implicit conversion).
Edit:
Unfortunately, you'll run into trouble if you try something like
List(1,2,3).map(square)
(specifically, you'll get a compile error like "could not find implicit value for evidence parameter of type Numeric[T]". To avoid this issue, you can overloadsquare
to return a function:Hopefully someone with a better understanding of the type inferencer will explain why that is.
Alternatively, one can call
List(1,2,3).map(square(_))
, as Derek Williams pointed out in the scala-user mailing list thread.