使用泛型类型定义的函数

时间:2014-08-13 21:27:34

标签: arrays scala

我搜索了一会儿,但我无法找到这个问题的明确和令人满意的答案。

假设我有这个小函数来计算数组的平均值:

def meanofArray(s:Array[Double]) : Double = s.sum/s.length

问题是Array 是Double。 例如,如果我有这个数组:

val x = Array( 1 , 2 , 3 , 4 ) 

并拨打电话:

println(meanofArray(x))

我发现错误:Array [Int]                 必需:数组[双]

如何实现meanofArray以便能够接受任何类型的Int,Long,Float和Double而没有错误?

我的想法是通用类型:

def meanofArray(s:Array[T]) : Double = s.sum/s.length

但我无法让它发挥作用。

欢迎任何其他想法!

3 个答案:

答案 0 :(得分:3)

您遇到的问题证明了类型抽象的美妙。

仅基于您提供的功能的签名

def meanofArray(s:Array[T]) : T

我们对这个功能可以做什么和不能做什么有很多了解,只要它不会做反射当然的阴影。它不能做像排序数组,找到总和等等。基于Scala的一些不幸的特性,有些事情我们无法确定它不会做,比如使用equals或{{1对于某些toString

您需要在函数签名中声明有关类型T的一些其他信息。

T

此处,我们声明def meanofArray[T](s: Array[T])(implicit ev: Numeric[T]): Double 必须定义Numeric[T]定义并在调用网站的范围内。 T提供了执行所需计算所需的函数定义。我们现在声明这个函数可以做更多的事情,比如对数组进行排序或找到总和。

您正在寻找的实施......

Numeric[T]

编辑:将def meanofArray[T](s: Array[T])(implicit ev: Numeric[T]): Double = s.view.map(ev.toDouble).sum / s.length 映射到s以查看以减少溢出的可能性。取自@Eastsun的回答。在我看来,隐含地Array[Double]优先于Numeric[T]的隐式视图。

答案 1 :(得分:1)

这是您想要的(参数的mean类型为Seq[A],以便您可以将其用作mean(List(1, 2, 3))mean("ABCDEFG")):

scala> def mean[A](arr: Seq[A])(implicit view: A => Double): Double = 
         (arr map view sum) / arr.size
mean: [A](arr: Seq[A])(implicit view: A => Double)Double

scala> mean(Array(1, 2, 3, 4))
res0: Double = 2.5

与@drstevens的解决方案比较:

scala> def meanofArray[T](s: Array[T])(implicit ev: Numeric[T]): Double = 
     |   ev.toDouble(s.sum) / s.length
meanofArray: [T](s: Array[T])(implicit ev: scala.math.Numeric[T])Double

scala> meanofArray(Array[Byte](111, 111, 111, 111))
res3: Double = -17.0  //Wrong!!!

scala> mean((Array[Byte](111, 111, 111, 111)))
res4: Double = 111.0 //Right !!!

答案 2 :(得分:0)

这是我能提出的最简洁的解决方案。

def mean[A <% Double : Numeric](seq:Seq[A]) = seq.sum/seq.length

这里,Seq.sum需要A的证据符合数字类型。 (类型参数中的:) 要实现这种划分,seq.sum的结果应该可以看作是一个双倍。总而言之,结果是Double类型

的结果