O que se entende por tipos dependentes de caminho de Scala?

125

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?

oxbow_lakes
fonte
2
@ Michel - Eu sei até o que são PDTs; Eu esperava que o SO pudesse ser enriquecido com uma resposta!
Ox4_lakes
1
Espero que haja uma resposta concisa depois de ler CH12 sobre PDT
empilhador

Respostas:

165

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 Coordinatedepende da instância da Boardqual 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 occupiedo 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
Daniel C. Sobral
fonte
2
+1 para a resposta. Achei a última frase confusa: você diz 'segurança de tipo que depende de valores e não apenas de tipos'. Para mim, isso soa como tipos dependentes, mas os tipos dependentes do caminho não dependem dos valores em si. Você também acha confuso?
Matthew Farwell
4
@Matthew eu entendo o que você está dizendo, mas dependente de caminho tipos fazer depender de valores, mesmo que ele não fornece a flexibilidade normalmente associada a tipos dependentes.
Daniel C. Sobral
1
Exatamente, é isso que eu quero dizer. Inicialmente, li que o tipo dependia dos valores passados ​​para o construtor, não do b1 / b2. Eu entendo agora, mas levei algumas leituras para entender.
Matthew Farwell
3
A explicação mais fácil é que os tipos dependentes de caminho são apenas classes com fechamento, exatamente da mesma maneira que as funções podem vincular variáveis ​​do escopo.
polkovnikov.ph
1
Mas talvez haja uma diferença fundamental nessa analogia: uma ligação ocorre no tempo de execução (para fechamentos) e a outra ligação ocorre no tempo de compilação (para tipos dependentes de caminho).
jhegedus