I suggest something like this:
sealed abstract class Dim(val dimension:Int) object Dim { class One extends Dim(1) class Two extends Dim(2) class Three extends Dim(3) implicit object One extends One implicit object Two extends Two implicit object Three extends Three } case class Vec[D <: Dim](values: Vector[Double])(implicit dim:D) { require(values.size == dim.dimension) def apply(i: Int) = values(i) def *(k: Double) = Vec[D]( values.map(_*k) ) def +(that: Vec[D]) = Vec[D]( ( values zip that.values ) map { pair => pair._1 + pair._2 }) override lazy val toString = values.mkString("Vec(",", ",")") }
Of course, you can only get time checks on the length of the vector this way, but, as others have already pointed out, you need something like elementary numbers or other font-level programming methods to achieve compile-time checks.
import Dim._ val a = Vec[Two](Vector(1.0,2.0)) val b = Vec[Two](Vector(1.0,3.0)) println(a + b) //--> Vec(2.0, 5.0) val c = Vec[Three](Vector(1.0,3.0)) //--> Exception in thread "main" java.lang.ExceptionInInitializerError //--> at scalatest.vecTest.main(vecTest.scala) //--> Caused by: java.lang.IllegalArgumentException: requirement failed
source share