Я снова играл со scala, тестируя некоторые функции проверки типа языка. Я пытаюсь реализовать векторную библиотеку, предназначенную для использования с графикой, и я хочу максимально использовать средство проверки типов scala, чтобы при его использовании получать ранние предупреждения о времени компиляции. Что у меня есть до сих пор.
trait VecT
abstract sealed class Vec[T,V[T] <: VecT](elems: T*)(implicit num: VecIntegral[T]) extends VecT {
import num._
def +(v: V[T]): V[T] = ???
def -(v: V[T]): V[T] = ???
def cross(v: V[T]): V[T] = ???
def dot(v: V[T]): T = ???
def unary_-(): V[T] = ???
def *(scalar: T): V[T] = ???
def abs: T = ???
def *(v: V[T]): V[T] = cross(v)
def apply(n: Int): T = ???
}
class Vec2[T](x: T, y: T)(implicit num: VecIntegral[T]) extends Vec[T, Vec2](x,y)
class Vec3[T](x: T, y: T, z: T)(implicit num: VecIntegral[T]) extends Vec[T, Vec3](x,y,z)
это позволяет мне выполнять проверку времени компиляции для операций, например, даже если оператор +
реализован в классе abstract
(new Vec3[Int](1,2,3)) + (new Vec3[Int](1,2,3))
(new Vec3[Int](1,2,3)) + (new Vec2[Int](1,2)) // Failes compilation
чего я хочу.
Все идет нормально. Теперь я хотел бы, чтобы функция карты была реализована в абстрактном классе, например
def map[A](f: T => A): V[A] = Vec(elems.map(f):_*)
Так что моя попытка реализовать это состояла бы в том, чтобы создать общую фабрику Vec.
object Vec {
def apply[T, V[T] <: VecT](elemes: T*)(implicit num: VecIntegral[T]): V[T] = elems match {
case Seq(x,y) => new V[T](x,y)
case Seq(x,y,z) => new V[T](x,y,z)
}
но это не сработает, expression of type V does not comform to exptected type V[T]
Итак, мой вопрос. Есть ли какой-нибудь «хороший» общий способ реализации такой фабрики?