Scala 如何使用数字[T]表示任何数字类型的零
我有一段Scala代码,我想让它更通用。我知道存在Scala 如何使用数字[T]表示任何数字类型的零,scala,generics,type-inference,typeclass,zero,Scala,Generics,Type Inference,Typeclass,Zero,我有一段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]): Ma
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)) }
}
我想写这样的东西(只写一次),其中零值自动转换为aB
类型
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)) }
}
试一试
或
或
导入提供隐式转换infixNumericOps
m1 ++ m2.map { case (k, v) => k -> (infixNumericOps(v) + m1.getOrElse(k, num.zero)) }
因此,我们不必像第一个示例中那样显式使用
Numeric.plus
。@LuisMiguelMejíaSuárez是import num.。
风格不受欢迎?我经常在宏中看到这种风格,例如,import c.universe.\u
。不,这很好,我指的是当必须隐式地使用调用隐式时,使用上下文边界没有任何价值。但这只是我自己的一种风格偏好,因此我只会使用一个隐式参数来命名它,并像您一样调用import。@LuisMiguelMejíaSuárez我找到了一个不错的理由,支持Philip Schwarz不命名implicits of,在这里它是这样说的“givens或implicits的要点是编译器将为您生成它们,那么您为什么要麻烦给它们命名呢?“有趣。然而,这张幻灯片在创建隐式而不是使用隐式时提到的更多,在这种情况下,我同意不必在Scala 3上命名它们会更好。现在,在方法/函数的上下文中。我确实认为,如果所有类型类都提供一个类似于Monoid[T]
(并应用于companion)的召唤器,那么只使用上下文边界将是一个很好的论据。但是由于很多人没有这样的参数,而且隐式的对我来说太冗长了,所以我更喜欢只使用普通的隐式参数。
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)) }
}
m1 ++ m2.map { case (k, v) => k -> (infixNumericOps(v) + m1.getOrElse(k, num.zero)) }