Как использовать Numeric [T] для представления нуля любого числового типа - PullRequest
3 голосов
/ 19 октября 2019

У меня есть фрагмент кода Scala, который я хотел бы сделать более общим. Я знаю, что Numeric[T] существует, но я не уверен, как его использовать.

  def sumMaps[A](m1: Map[A, Long], m2: Map[A, Long]): Map[A, Long] = {
    m1 ++ m2.map { case (k, v) => k -> (v + m1.getOrElse(k, 0L)) }
  }

  def sumMaps[A](m1: Map[A, Int], m2: Map[A, Int]): Map[A, Int] = {
    m1 ++ m2.map { case (k, v) => k -> (v + m1.getOrElse(k, 0)) }
  }

  def sumMaps[A](m1: Map[A, Double], m2: Map[A, Double]): Map[A, Double] = {
    m1 ++ m2.map { case (k, v) => k -> (v + m1.getOrElse(k, 0)) }
  }

Я хотел бы написать что-то вроде этого (только один раз), где нулевое значение автоматически преобразуетсяк типу B.

  def sumMaps[A, B: Numeric[?]](m1: Map[A, B], m2: Map[A, B]): Map[A, B] = {
    m1 ++ m2.map { case (k, v) => k -> (v + m1.getOrElse(k, 0)) }
  }

1 Ответ

5 голосов
/ 19 октября 2019

Попробуйте

def sumMaps[A, B](m1: Map[A, B], m2: Map[A, B])(implicit num: Numeric[B]): Map[A, B] = {
  m1 ++ m2.map { case (k, v) => k -> num.plus(v, m1.getOrElse(k, num.zero)) }
}

или

import Numeric.Implicits._
def sumMaps[A, B](m1: Map[A, B], m2: Map[A, B])(implicit num: Numeric[B]): Map[A, B] = {
  m1 ++ m2.map { case (k, v) => k -> (v + m1.getOrElse(k, num.zero)) }
}

или

def sumMaps[A, B: Numeric](m1: Map[A, B], m2: Map[A, B]): Map[A, B] = {
  val num = implicitly[Numeric[B]]
  import num._
  m1 ++ m2.map { case (k, v) => k -> (v + m1.getOrElse(k, zero)) }
}

Импорт обеспечивает неявное преобразование infixNumericOps

m1 ++ m2.map { case (k, v) => k -> (infixNumericOps(v) + m1.getOrElse(k, num.zero)) }

поэтому нам не нужно явно использовать Numeric.plus, как в первом примере.

...