ade*_*rtc 11 type-systems scala tuples compile-time
是否可以Vector在编译时强制传入方法的大小?我想使用空间中的一组点来模拟一个n维欧几里德空间,这些点看起来像这样(这就是我现在所拥有的):
case class EuclideanPoint(coordinates: Vector[Double]) {
def distanceTo(desination: EuclieanPoint): Double = ???
}
Run Code Online (Sandbox Code Playgroud)
如果我有一个通过创建的坐标EuclideanPoint(Vector(1, 0, 0)),它是一个3D欧几里德点.鉴于此,我想确保调用中传递的目标点具有distanceTo相同的维度.
我知道我可以通过使用Tuple1to 来做到这一点Tuple22,但我想代表许多不同的几何空间,如果我用Tuples 做的话,我会为每个空间写22个类- 有更好的方法吗?
Tra*_*own 12
可以通过多种方式实现这一点,这些方式或多或少都与Randall Schulz在评论中描述的方式相似.该无形库提供了一个特别方便的实现,它可以让你得到相当接近的东西,你想这样的内容:
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
)
}
Run Code Online (Sandbox Code Playgroud)
现在您可以编写以下内容:
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))
Run Code Online (Sandbox Code Playgroud)
和:
scala> orig2d distanceTo unit2d
res0: Double = 1.4142135623730951
scala> orig3d distanceTo unit3d
res1: Double = 1.7320508075688772
Run Code Online (Sandbox Code Playgroud)
但不是:
scala> orig2d distanceTo unit3d
<console>:15: error: type mismatch;
found : EuclideanPoint[shapeless.Nat._3]
required: EuclideanPoint[shapeless.Nat._2]
orig2d distanceTo unit3d
^
Run Code Online (Sandbox Code Playgroud)
Sized它带有许多不错的功能,包括一些带有长度静态保证的集合操作.我们可以写下面的例子:
val somewhere = EuclideanPoint(Sized(0.0) ++ Sized(1.0, 0.0))
Run Code Online (Sandbox Code Playgroud)
并且在三维空间中有一个普通的旧点.