如何在Scala中实现一个通用的数学函数

问题描述:

我刚刚开始使用Scala,而我认为应该很容易的东西很难弄清楚。我想实现以下功能:如何在Scala中实现一个通用的数学函数

def square(x:Int):Int = { x * x }

这只是正常的,但如果我想尝试做任何一种数量的此功能工作,我希望能够做到以下几点:

def square[T <: Number](x : T):T = { x * x }

这抱怨说:错误:值*是不是类型参数T

我需要实现此一特质中的一员?

+0

对于后人来说,给这个问题一个更具体的标题可能是有用的,比如“我如何在Scala中实现通用数学函数?”。 – 2010-10-30 17:25:59

+0

同意,谢谢。 – jimmyb 2011-05-05 15:49:05

这是我在堆栈溢出或关于Scala的first questions之一。问题在于Scala保持与Java的兼容性,这意味着它的基本数字类型等同于Java的基元。

问题在于Java基元不是类,因此没有允许“数字”超类型的类层次结构。

说得透彻一点,Java和,因此,Scala中,并没有看到一个Double+和一个Int+之间的共同点。

方式斯卡拉终于绕开这个限制得到的是通过使用Numeric,和它的子类FractionalIntegral,在所谓的类型类模式。基本上,你用这样的:

def square[T](x: T)(implicit num: Numeric[T]): T = { 
    import num._ 
    x * x 
} 

或者,如果你不需要任何的数字运算,但你打电话做的方法,你可以使用方面的约束语法类型声明:

def numberAndSquare[T : Numeric](x: T) = x -> square(x) 

欲了解更多信息,请参阅我自己的问题的答案。

+1

很好的解释。我必须为Typeclass模式谷歌 - 不知道存在。谢谢。 – Collin 2010-10-30 14:35:17

+0

如果你有这个,但是: 'def squareAddOne [T](x:T)(implicit num:Numeric [T]):T = {import num._; x * x + 1}' 如何将Int添加到数字中? – 2016-08-01 15:00:00

+0

哦,我想我的问题是在这里回答:http://*.com/a/2388386/901263 – 2016-08-01 15:03:30

您可以定义square为:

def square[T: Numeric](x: T): T = implicitly[Numeric[T]].times(x,x) 

这种方法的优势在于,它将为具有一个隐式转换为数字[T](即整型,浮点型,双,字符任何类型T的工作, BigInt,...或您为其提供隐式转换的任何类型)。

编辑: 不幸的是,如果你尝试像List(1,2,3).map(square)(特别是你遇到麻烦,你会得到一个编译错误,如“无法找到数字类型[T]的证据参数内含价值”为了避免这个问题,你可以重载square返回一个函数:

object MyMath { 
    def square[T: Numeric](x: T) = implicitly[Numeric[T]].times(x,x) 
    def square[T: Numeric]: T => T = square(_) 
} 

希望有人能够更好地理解类型inferencer将解释这是为什么

另外,可以拨打如Derek Williams在scala-user mailing list thread中指出的那样,。