我搜索了一会儿,但我无法找到这个问题的明确和令人满意的答案。
假设我有这个小函数来计算数组的平均值:
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
但我无法让它发挥作用。
欢迎任何其他想法!
答案 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
类型