I have a scenario where I would like to call sum on a sequence of (Double, Double) tuples. Ideally I would like to do something like the following:
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
}
}
But when I call sum:
val seq: Seq[(Double, Double)] = ...
val sum = seq.sum
I get a compiler error:
could not find implicit value for parameter num: Numeric[(Double, Double)]
Is there a way to implement such an implicit?
You seem to confuse conditional implicit
with implicit conversion
With the former you're specifying that the data type
(T, T)
(akascala.Tuple2[T, T]
) is an instance of the type classNumeric
provided thatT
is an instance of the type class. This means that if there is an implicit of the typeNumeric[T]
then there is an implicit of the typeNumeric[(T, T)]
. In Scala 3 the type of this conditional implicit isNumeric[T] ?=> Numeric[(T, T)]
(akaContextFunction1[Numeric[T], Numeric[(T, T)]]
).With the latter you're specifying that the data type
Numeric[T]
can be used where the data typeNumeric[(T, T)]
is expected and this functionNumeric[T] => Numeric[(T, T)]
(akaFunction1[Numeric[T], Numeric[(T, T)]]
) should be used for such transformation automatically.I guess you meant the former. So add
implicit
to the parameter(num: Numeric[T])
making it an implicit parameter(implicit num: Numeric[T])
. Your code will compile then.You can refresh your understanding implicits in 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.html https://docs.scala-lang.org/tour/implicit-conversions.html
https://docs.scala-lang.org/scala3/book/ca-contextual-abstractions-intro.html ...
https://docs.scala-lang.org/scala3/reference/contextual/index.html ...
You can also rewrite your definition using a context bound (
: Numeric
), importing implicits, extension methods aka type-class syntax (.toInt
,.+(...)
), and type-class materializer (Numeric.apply[T]
)What is a "context bound" in Scala?