What is meant by Scala's path-dependent types?

oxbow_lakes picture oxbow_lakes · Apr 22, 2010 · Viewed 12.2k times · Source

I've heard that Scala has path-dependent types. It's something to do with inner-classes but what does this actually mean and why do I care?

Answer

Daniel C. Sobral picture Daniel C. Sobral · Apr 22, 2010

My favorite example:

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

So, the type of Coordinate is dependent on the instance of Board from which it was instantiated. There are all sort of things that can be accomplished with this, giving a sort of type safety that is dependent on values and not types alone.

This might sound like dependent types, but it is more limited. For example, the type of occupied is dependent on the value of Board. Above, the last line doesn't work because the type of c2 is b2.Coordinate, while occupied's type is Set[b1.Coordinate]. Note that one can use another identifier with the same type of b1, so it is not the identifier b1 that is associated with the type. For example, the following works:

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