11

Vectorコンパイル時にメソッドに渡されたのサイズを強制することは可能ですか? 次のような空間内のポイントのコレクションを使用して、n 次元のユークリッド空間をモデル化したいと思います (これが私が今持っているものです)。

case class EuclideanPoint(coordinates: Vector[Double]) {
  def distanceTo(desination: EuclieanPoint): Double = ???
}

で作成された座標がある場合EuclideanPoint(Vector(1, 0, 0))、それは 3D ユークリッド ポイントです。distanceToそのため、への呼び出しで渡された宛先ポイントが同じ次元であることを確認したいと思います。

Tuple1toを使用してこれを実行できることはわかっていますがTuple22、多くの異なる幾何学的空間を表現したいので、Tuples を使用した場合、空間ごとに 22 個のクラスを作成することになります。より良い方法はありますか?

4

2 に答える 2

12

これは、Randall Schulz がコメントで説明したものと多かれ少なかれ似ているさまざまな方法で行うことができます。Shapeless ライブラリは、特に便利な実装を提供します。これにより、次のように、必要なものにかなり近いものが得られます。

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))

そして、三次元空間に普通の古い点を持ってください。

于 2013-02-07T00:52:09.197 に答える
2

http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-scala/のように、自然数のタイプレベルのエンコードを行うことで、自分で何かを行うことができます。次に、NaturalによってVectorをパラメータ化します。追加の依存関係は必要ありませんが、Shapelessを使用するよりもおそらく複雑になります。

于 2013-02-07T04:59:14.500 に答える