web-dev-qa-db-ja.com

Scalaのパス依存型とはどういう意味ですか?

Scalaにはパスに依存する型があると聞きました。これは内部クラスと関係があるのですが、これは実際には何を意味し、なぜ私は気にするのですか?

122
oxbow_lakes

私のお気に入りの例:

case class Board(length: Int, height: Int) {
  case class Coordinate(x: Int, y: Int) { 
    require(0 <= x && x < length && 0 <= y && y < height) 
  }
  val occupied = scala.collection.mutable.Set[Coordinate]()
}

val b1 = Board(20, 20)
val b2 = Board(30, 30)
val c1 = b1.Coordinate(15, 15)
val c2 = b2.Coordinate(25, 25)
b1.occupied += c1
b2.occupied += c2
// Next line doesn't compile
b1.occupied += c2

したがって、Coordinateのタイプは、インスタンス化されたBoardのインスタンスに依存します。これで達成できるすべての種類のものがあり、型のみではなく値に依存する一種の型安全性を提供します。

これは依存型のように聞こえるかもしれませんが、より制限されています。たとえば、occupiedのタイプはBoardの値に依存します。上記では、occupiedのタイプがc2であるのに対し、b2.CoordinateのタイプはSet[b1.Coordinate]であるため、最後の行は機能しません。同じタイプのb1を持つ別の識別子を使用できるため、そのタイプに関連付けられているのはidentifierb1ではないことに注意してください。たとえば、次の作品:

val b3: b1.type = b1
val c3 = b3.Coordinate(10, 10)
b1.occupied += c3
161