Ouvi dizer que Scala tem tipos dependentes de caminho. Tem algo a ver com classes internas, mas o que isso realmente significa e por que eu me importo?
Ouvi dizer que Scala tem tipos dependentes de caminho. Tem algo a ver com classes internas, mas o que isso realmente significa e por que eu me importo?
Respostas:
Meu exemplo favorito:
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
Portanto, o tipo de Coordinate
depende da instância da Board
qual foi instanciado. Há todo tipo de coisa que pode ser realizada com isso, fornecendo um tipo de segurança de tipo dependente de valores e não apenas de tipos.
Pode parecer tipos dependentes, mas é mais limitado. Por exemplo, o tipo de occupied
é dependente do valor de Board
. Acima, a última linha não funciona porque o tipo de c2
é b2.Coordinate
, enquanto occupied
o tipo é Set[b1.Coordinate]
. Observe que é possível usar outro identificador com o mesmo tipo de b1
, portanto, não é o identificador b1
associado ao tipo. Por exemplo, o seguinte funciona:
val b3: b1.type = b1
val c3 = b3.Coordinate(10, 10)
b1.occupied += c3