协方差在简单函数中的工作原理



我试图简单使用Scala协方差原理。我希望下面的 max 和 sum 方法适用于IntDouble或任何其他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)