Que signifient les types dépendants du chemin de Scala?

125

J'ai entendu dire que Scala a des types dépendant du chemin. C'est quelque chose à voir avec les classes internes, mais qu'est-ce que cela signifie réellement et pourquoi est-ce que je m'en soucie?

oxbow_lakes
la source
2
@Michel - Je sais même ce que sont les PDT; J'espérais que SO pourrait être enrichi d'une réponse!
oxbow_lakes
1
J'espère qu'il y aura une réponse laconique après avoir lu ch12 sur PDT
stacker

Réponses:

165

Mon exemple préféré:

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

Ainsi, le type de Coordinatedépend de l'instance à Boardpartir de laquelle il a été instancié. Il y a toutes sortes de choses qui peuvent être accomplies avec cela, donnant une sorte de sécurité de type qui dépend des valeurs et non des seuls types.

Cela peut ressembler à des types dépendants, mais c'est plus limité. Par exemple, le type de occupieddépend de la valeur de Board. Ci-dessus, la dernière ligne ne fonctionne pas car le type de c2est b2.Coordinate, tandis que occupiedle type de est Set[b1.Coordinate]. Notez que l'on peut utiliser un autre identifiant avec le même type de b1, donc ce n'est pas l' identifiant b1 qui est associé au type. Par exemple, les travaux suivants:

val b3: b1.type = b1
val c3 = b3.Coordinate(10, 10)
b1.occupied += c3
Daniel C. Sobral
la source
2
+1 pour la réponse. J'ai trouvé la dernière phrase déroutante: vous dites «sécurité de type qui dépend des valeurs et non des seuls types». Pour moi, cela ressemble à des types dépendants, mais les types dépendants du chemin ne dépendent pas des valeurs en soi. Pensez-vous que c'est aussi déroutant?
Matthew Farwell
4
@Matthew Je comprends ce que vous dites, mais les types dépendants de chemin ne dépends des valeurs, même si elle ne fournit pas la flexibilité normalement associés à des types dépendants.
Daniel C. Sobral
1
Exactement, c'est ce que je veux dire. Au départ, j'ai lu que le type dépendait des valeurs transmises au constructeur, pas du b1 / b2. Je comprends maintenant, mais il m'a fallu quelques lectures pour l'obtenir.
Matthew Farwell
3
L'explication la plus simple est que les types dépendant du chemin ne sont que des classes avec des fermetures, exactement de la même manière que les fonctions peuvent lier des variables à partir de la portée.
polkovnikov.ph
1
Mais il y a peut-être une différence fondamentale à cette analogie: une liaison a lieu au moment de l'exécution (pour les fermetures) et l'autre liaison a lieu au moment de la compilation (pour les types dépendant du chemin).
jhegedus