如何为元组编写隐式Numeric以实现序列sum操作?
解决(Double, Double)序列调用sum的隐式Numeric问题
你的问题出在隐式转换方法的定义方式上,编译器无法自动触发从Numeric[Double]到Numeric[(Double, Double)]的转换。以下是可行的修正方案:
修正后的隐式Numeric实例定义
将原隐式方法调整为上下文绑定的形式,确保编译器能正确推导依赖的Numeric[T]实例:
implicit def tupleNumeric[T: Numeric]: Numeric[(T, T)] = new Numeric[(T, T)] { private val num = implicitly[Numeric[T]] def plus(x: (T, T), y: (T, T)): (T, T) = (num.plus(x._1, y._1), num.plus(x._2, y._2)) def minus(x: (T, T), y: (T, T)): (T, T) = (num.minus(x._1, y._1), num.minus(x._2, y._2)) def times(x: (T, T), y: (T, T)): (T, T) = (num.times(x._1, y._1), num.times(x._2, y._2)) def negate(x: (T, T)): (T, T) = (num.negate(x._1), num.negate(x._2)) def fromInt(x: Int): (T, T) = (num.fromInt(x), num.fromInt(x)) def toInt(x: (T, T)): Int = num.toInt(x._1) + num.toInt(x._2) def toLong(x: (T, T)): Long = num.toLong(x._1) + num.toLong(x._2) def toFloat(x: (T, T)): Float = num.toFloat(x._1) + num.toFloat(x._2) def toDouble(x: (T, T)): Double = num.toDouble(x._1) + num.toDouble(x._2) def compare(x: (T, T), y: (T, T)): Int = num.compare(x._1, y._1) match { case c if c == 0 => num.compare(x._2, y._2) case c => c } }
关键修改点
- 使用
[T: Numeric]上下文绑定,替代原方法的num: Numeric[T]参数,让编译器更明确地识别需要依赖的隐式实例。 - 通过
implicitly[Numeric[T]]获取上下文绑定的Numeric实例,保证逻辑和原代码一致。
测试验证
确保上述隐式定义在调用sum的作用域内可见(比如同一对象、包对象或已导入),即可正常调用:
val seq: Seq[(Double, Double)] = Seq((1.5, 2.5), (3.5, 4.5)) val sum = seq.sum // 结果为(5.0, 7.0)
可选方案(第三方库)
如果使用Scala 2.13+且允许引入第三方库,cats库提供了现成的Monoid和Numeric实例支持元组,可以直接导入使用,无需自定义实现。
内容的提问来源于stack exchange,提问作者user79074
相关产品推荐
相关产品推荐

