Scala рассматривает только первый список аргументов для разрешения перегрузки в соответствии со спецификацией .Оба mean
метода считаются одинаково конкретными и неоднозначными.
Но для неявного разрешения также учитываются последствия в области видимости, поэтому обходным путем может быть использование шаблона магнита или класса типов.Вот пример использования шаблона магнита, который, я считаю, проще:
def mean[T](data: MeanMagnet[T]): data.Out = data.mean
sealed trait MeanMagnet[T] {
type Out
def mean: Out
}
object MeanMagnet {
import language.implicitConversions
type Aux[T, O] = MeanMagnet[T] { type Out = O }
implicit def fromFractional[T](
data: Iterable[T]
)(
implicit number: Fractional[T]
): MeanMagnet.Aux[T, T] = new MeanMagnet[T] {
override type Out = T
override def mean: Out = {
import number._
val sum = data.foldLeft(zero)(plus)
div(sum, fromInt(data.size))
}
}
implicit def fromIntegral[T](
data: Iterable[T]
)(
implicit number: Integral[T]
): MeanMagnet.Aux[T, Double] = new MeanMagnet[T] {
override type Out = Double
override def mean: Out = {
import number._
val sum = data.foldLeft(zero)(plus)
sum.toDouble / data.size
}
}
}
С этим определением он работает нормально:
scala> mean(List(1,2,3,4))
res0: Double = 2.5
scala> mean(List(1.0, 2.0, 3.0, 4.0))
res1: Double = 2.5
scala> mean(List(1.0f, 2.0f, 3.0f, 4.0f))
res2: Float = 2.5