可以通過很多方式做到這一點,所有這些看起來都像Randall Schulz在評論中所描述的那樣。該Shapeless library提供了一個特別方便的實現,它可以讓你想這樣你會得到什麼很接近的東西:
import shapeless._
case class EuclideanPoint[N <: Nat](
coordinates: Sized[IndexedSeq[Double], N] { type A = Double }
) {
def distanceTo(destination: EuclideanPoint[N]): Double =
math.sqrt(
(this.coordinates zip destination.coordinates).map {
case (a, b) => (a - b) * (a - b)
}.sum
)
}
現在,你可以寫:
val orig2d = EuclideanPoint(Sized(0.0, 0.0))
val unit2d = EuclideanPoint(Sized(1.0, 1.0))
val orig3d = EuclideanPoint(Sized(0.0, 0.0, 0.0))
val unit3d = EuclideanPoint(Sized(1.0, 1.0, 1.0))
和:
scala> orig2d distanceTo unit2d
res0: Double = 1.4142135623730951
scala> orig3d distanceTo unit3d
res1: Double = 1.7320508075688772
但不是:
scala> orig2d distanceTo unit3d
<console>:15: error: type mismatch;
found : EuclideanPoint[shapeless.Nat._3]
required: EuclideanPoint[shapeless.Nat._2]
orig2d distanceTo unit3d
^
Sized
附帶了許多不錯的功能,其中包括一些收集操作,攜帶長度的靜態保證。我們可以寫下例如:
val somewhere = EuclideanPoint(Sized(0.0) ++ Sized(1.0, 0.0))
並且在三維空間中有一個普通的老點。
我不能很好地意識到這是一個_answer_,但它可能有資格作爲一個想法......我想到的第一件事是將一個Value Class(2.10中的new)和路徑依賴類型結合起來代表特定整數的類型。我真的不知道這是否可以起作用。當工作結束的時候,我可能會嘗試一下...請參閱SIP 15:http://docs.scala-lang.org/overviews/core/value-classes.html –
這種約束可以用「類型編程」。例如,請參閱[Apocalisp博客系列](http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-scala/),特別是HList。 –