scala 如何为元组编写隐式Numeric

kokeuurv  于 2023-02-16  发布在  Scala
关注(0)|答案(1)|浏览(158)

我有一个场景,我想对一个(Double,Double)元组序列调用sum。理想情况下,我想做如下事情:

implicit def toTupleNumeric[T](num: Numeric[T]) = new Numeric[(T, 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
    }
}

但是当我打电话给sum:

val seq: Seq[(Double, Double)] = ...
val sum = seq.sum

出现编译器错误:
找不到参数num的隐式值:数值[(双精度,双精度)]
有没有办法实现这样的隐式?

li9yvcax

li9yvcax1#

你好像把条件隐含

implicit def toTupleNumeric[T](implicit num: Numeric[T]): Numeric[(T, T)] = ...

使用隐式转换

implicit def toTupleNumeric[T](num: Numeric[T]): Numeric[(T, T)] = ...

对于前者,您要指定数据类型(T, T)(aka scala.Tuple2[T, T])是类型类Numeric的示例,前提是T是类型类的示例。这意味着如果存在类型Numeric[T]的隐式,则存在类型Numeric[(T, T)]的隐式。在Scala 3中,这个隐式条件的类型是Numeric[T] ?=> Numeric[(T, T)](又名ContextFunction1[Numeric[T], Numeric[(T, T)]])。
对于后者,您将指定数据类型Numeric[T]可用于预期的数据类型Numeric[(T, T)],并且函数Numeric[T] => Numeric[(T, T)](aka Function1[Numeric[T], Numeric[(T, T)]])应自动用于此类转换。
我猜你指的是前者。所以把implicit加到参数(num: Numeric[T])上,使它成为一个隐式参数(implicit num: Numeric[T])。这样你的代码就可以编译了。
你可以重新理解Scala中的隐含含义:
Understanding implicit in Scala
What are type classes in Scala useful for?
Implicit conversion vs. type class
How can I chain implicits in Scala?
Why are implicit conversion deprecated in scala?
Can someone explain me implicit conversions in Scala?
Scala - Implicit conversion to implicit argument
Implicit conversion with implicit parameter
https://docs.scala-lang.org/tour/implicit-parameters.htmlhttps://docs.scala-lang.org/tour/implicit-conversions.html
https://docs.scala-lang.org/scala3/book/ca-contextual-abstractions-intro.html ...
一天...
您也可以使用上下文绑定(: Numeric)、导入隐式、扩展方法(又名类型-类语法(.toInt.+(...)))和类型-类物化器(Numeric.apply[T])重写定义。

import Numeric.Implicits._

implicit def toTupleNumeric[T: Numeric]: Numeric[(T, T)] =
  new Numeric[(T, T)] {
    override def plus(x: (T, T), y: (T, T)): (T, T) = (x._1 + y._1, x._2 + y._2)
    override def minus(x: (T, T), y: (T, T)): (T, T) = (x._1 - y._1, x._2 - y._2)
    override def times(x: (T, T), y: (T, T)): (T, T) = (x._1 * y._1, x._2 * y._2)
    override def negate(x: (T, T)): (T, T) = (-x._1, -x._2)
    override def fromInt(x: Int): (T, T) = (Numeric[T].fromInt(x), Numeric[T].fromInt(x))
    override def toInt(x: (T, T)): Int = x._1.toInt + x._2.toInt
    override def toLong(x: (T, T)): Long = x._1.toLong + x._2.toLong
    override def toFloat(x: (T, T)): Float = x._1.toFloat + x._2.toFloat
    override def toDouble(x: (T, T)): Double = x._1.toDouble + x._2.toDouble
    override def compare(x: (T, T), y: (T, T)): Int = Numeric[T].compare(x._1, y._1) match {
      case c if c == 0 => Numeric[T].compare(x._2, y._2)
      case c => c
    }
    override def parseString(str: String): Option[(T, T)] = ???
  }

What is a "context bound" in Scala?

相关问题