我想用一些靈活的方法實現一些通用的數學函數。 例如一個名爲meandot
函數聲明爲類似如何減少泛型方法中不需要的類型參數?
object Calc {
def meandot[..](xs: Array[Left], ys: Array[Right])(implicit ..): Result
}
其中meandot(xs, ys) = sum(x*y for x, y in zip(xs, ys))/length
當我調用meandot
無特殊類型的參數,它應該默認類型返回一個值。例如
scala> Calc.meandot(Array(1, 2), Array(1, 1))
res0: Int = 1
如果我調用meandot
與特殊類型的參數,它可以返回一個適當的值。
scala> Calc.meandot[Int, Int, Double](Array(1, 2), Array(1, 1))
res1: Double = 1.5
然而,在上面的前兩個類型參數是冗餘。我需要專門的唯一類型是返回類型。我想調用它簡化爲
scala> Calc.meandot2(Array(1, 2), Array(1, 1))
res2: Int = 1
scala> Calc.meandot2[Double](Array(1, 2), Array(1, 1))
res3: Double = 1.5
而且我找到了一種方法來實現它爲下面的代碼,它使用的是代理類MeanDotImp
。 但它似乎不那麼優雅。所以我想知道是否有更好的解決方案來減少泛型方法中不需要的類型參數?
trait Times[L, R, N] {
def times(x: L, y: R): N
}
trait Num[N] {
def zero: N = fromInt(0)
def one: N = fromInt(1)
def fromInt(i: Int): N
def plus(x: N, y: N): N
def div(x: N, y: N): N
}
abstract class LowTimesImplicits {
implicit val IID: Times[Int, Int, Double] = new Times[Int, Int, Double] {
def times(x: Int, y: Int): Double = x * y
}
}
object Times extends LowTimesImplicits {
implicit val III: Times[Int, Int, Int] = new Times[Int, Int, Int] {
def times(x: Int, y: Int): Int = x * y
}
}
object Num {
implicit val INT: Num[Int] = new Num[Int] {
def fromInt(i: Int): Int = i
def plus(x: Int, y: Int): Int = x + y
def div(x: Int, y: Int): Int = x/y
}
implicit val DOU: Num[Double] = new Num[Double] {
def fromInt(i: Int): Double = i
def plus(x: Double, y: Double): Double = x + y
def div(x: Double, y: Double): Double = x/y
}
}
object Calc {
def meandot[L, R, N](xs: Array[L], ys: Array[R])
(implicit t: Times[L, R, N], n: Num[N]): N = {
val total = (xs, ys).zipped.foldLeft(n.zero){
case(r, (x, y)) => n.plus(r, t.times(x, y))
}
n.div(total, n.fromInt(xs.length))
}
implicit class MeanDotImp[L, R](val marker: Calc.type) {
def meandot2[N](xs: Array[L], ys: Array[R])
(implicit t: Times[L, R, N], n: Num[N]): N = {
val total = (xs, ys).zipped.foldLeft(n.zero){
case(r, (x, y)) => n.plus(r, t.times(x, y))
}
n.div(total, n.fromInt(xs.length))
}
}
}
所以,你希望能夠調用'meandot [雙](...)',但仍保持開放調用'meandot [是int,short,浮點型](的選項。 ..)'(或某些這樣的)。這是這個想法嗎? – jwvh
@jwvh即使我只能調用'meandot [Double](Array [L],Array [R])'',其中'L,R'可以是'Int,Float,Double'等,也可以。 – Eastsun
如果你'重新做大量的數學,考慮https://github.com/non/spire – Reactormonk