我试图简单使用Scala协方差原理。我希望下面的 max 和 sum 方法适用于Int
、Double
或任何其他Numeric
类型的List
。 下面的代码返回以下错误:
type mismatch;
found: Int(2)
required: T1
in max(List(2,3,4))
object Main extends App {
class utils[+T1 <: Ordered[T1], +T2 <: Numeric[T1]] {
def max(input_list: List[T1]): T1 = {
def inside_max(i: Int, current_max: T1): T1 = {
if (i >= input_list.size) current_max
if (input_list(i) < current_max) {
inside_max(i + 1, current_max: T1)
} else {
inside_max(i + 1, input_list(i))
}
}
inside_max(0, input_list(0))
}
def sum(input_list: List[T2]): T2 = {
def inside_sum(i: Int, current_sum: T2): T2 = {
if (i >= input_list.size) current_sum
val new_sum: T2 = implicitly[Numeric[T2]](Numeric[T2]).plus(current_sum, input_list(i))
inside_sum(i + 1, new_sum)
}
inside_sum(1, input_list(0))
}
max(List(2,3,4))
}
}
您将方差与子类型和类型类混合在一起,这些是不同的概念。
在这种情况下,您实际上只想使用Numeric
类型类。
object Utils {
def max[T : Ordering](list: List[T]): Option[T] = {
import Ordering.Implicits._
@annotation.tailrec
def loop(remaining: List[T], currentMax: T): T =
remaining match {
case Nil =>
currentMax
case t :: tail =>
val newMax =
if (t >= currentMax)
t
else
currentMax
loop(
remaining = tail,
newMax
)
}
list match {
case Nil => None
case t :: tail => Some(loop(remaining = tail, currentMax = t))
}
}
def sum[T : Numeric](list: List[T]): T = {
import Numeric.Implicits._
def loop(remaining: List[T], acc: T): T =
remaining match {
case Nil =>
acc
case t :: tail =>
loop(
remaining = tail,
acc + t
)
}
loop(remaining = list, acc = Numeric[T].zero)
}
}
你可以像这样使用:
Utils.sum(List(1, 2, 3))
// res: Int = 6
Utils.sum(List.empty[Int])
// res: Int = 0
Utils.max(List.empty[Int])
// res: Option[Int] = None
Utils.max(List(1, 2, 3))
// res: Option[Int] = Some(3)