F-ограниченный полиморфизм не может быть добавлен к существующему классу Int
, потому что Int
- это просто то, что он есть, он ничего не знает о ваших Combiner
чертах, поэтому он не может расширять Combiner[Int]
. Вы можете обернуть каждый Int
во что-то вроде IntWrapper <: Combiner[IntWrapper]
, но это потратит немало памяти, и дизайн библиотеки вокруг F-ограниченного полиморфизма имеет тенденцию быть хитрым.
Вот предложение, основанное на специальном полиморфизме и классах типов:
object TestImplicits1 {
trait Combiner[T] {
def +(a: T, b: T): T
def *(a: T, b: T): T
}
object syntax {
object combiner {
implicit class CombinerOps[A](a: A) {
def +(b: A)(implicit comb: Combiner[A]) = comb.+(a, b)
def *(b: A)(implicit comb: Combiner[A]) = comb.*(a, b)
}
}
}
case class Complex(re: Double, im: Double)
implicit val complexCombiner: Combiner[Complex] = new Combiner[Complex] {
override def +(a: Complex, b: Complex): Complex = {
Complex(a.re + b.re, a.im + b.im)
}
override def *(a: Complex, b: Complex): Complex = {
Complex((a.re * b.re) - (a.im * b.im), a.re * b.im + b.re * a.im)
}
}
implicit val intCombiner: Combiner[Int] = new Combiner[Int] {
override def *(a: Int, b: Int): Int = a * b
override def +(a: Int, b: Int): Int = a + b
}
class Matrix[T: Combiner](entries: Vector[Vector[T]]) {
def frobeniusNormSq: T = {
import syntax.combiner._
entries.map(_.map(x => x * x).reduce(_ + _)).reduce(_ + _)
}
}
}
Я не знаю, что вы пытались сделать с помощью dot
, ваши x1
, x2
и ma
казались совершенно неиспользуемыми, поэтому я добавил вместо этого простой пример квадрата Фробениуса-нормы, просто чтобы показать, как классы типов и синтаксический сахар для операторов работают вместе. Пожалуйста, не ожидайте ничего похожего на «высокую производительность» - JVM традиционно никогда не заботился о прямоугольных массивах и сокращении чисел (по крайней мере, не на одном вычислительном узле; Spark & Co - это отдельная история). По крайней мере, ваш код не будет автоматически перенесен в оптимизированный код CUDA, это точно.