Co oznaczają typy zależne od ścieżki Scali?

125

Słyszałem, że Scala ma typy zależne od ścieżki. To ma coś wspólnego z klasami wewnętrznymi, ale co to właściwie oznacza i dlaczego mnie to obchodzi?

oxbow_lakes
źródło
2
@Michel - nawet wiem, co to są PDT; Miałem nadzieję, że odpowiedź na SO można wzbogacić!
oxbow_lakes
1
Mam nadzieję, że jest zwięzła odpowiedź po przeczytaniu rozdziału 12 o PDT
stacker

Odpowiedzi:

165

Mój ulubiony przykład:

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

Tak więc typ Coordinatejest zależny od instancji, Boardz której została utworzona. Jest wiele rzeczy, które można w ten sposób osiągnąć, dając rodzaj bezpieczeństwa zależnego od wartości, a nie samych typów.

Może to brzmieć jak typy zależne, ale jest bardziej ograniczone. Na przykład typ occupiedzależy od wartości Board. Powyżej ostatnia linia nie działa, ponieważ typ c2to b2.Coordinate, a occupiedtyp to Set[b1.Coordinate]. Należy zauważyć, że można użyć innego identyfikatora tego samego typu b1, więc nie jest to identyfikator b1 powiązany z typem. Na przykład działa to:

val b3: b1.type = b1
val c3 = b3.Coordinate(10, 10)
b1.occupied += c3
Daniel C. Sobral
źródło
2
+1 za odpowiedź. Ostatnie zdanie wydało mi się zagmatwane: mówisz „bezpieczeństwo typów, które zależy od wartości, a nie samych typów”. Dla mnie brzmi to jak typy zależne, ale typy zależne od ścieżki nie zależą od wartości jako takich. Czy uważasz, że to też jest mylące?
Matthew Farwell,
4
@Matthew rozumiem, co mówisz, ale typy ścieżek zależny zrobić zależy od wartości, nawet jeśli nie zapewniają elastyczność normalnie związanego z typów zależnych.
Daniel C. Sobral,
1
Dokładnie, o to mi chodzi. Początkowo przeczytałem, że typ zależy od wartości przekazywanych do konstruktora, a nie od b1 / b2. Rozumiem to teraz, ale zajęło mi to kilka czytań.
Matthew Farwell,
3
Najłatwiejszym wyjaśnieniem jest to, że typy zależne od ścieżki to po prostu klasy z zamknięciami, dokładnie w ten sam sposób, w jaki funkcje mogą wiązać zmienne z zakresu.
polkovnikov.ph
1
Ale może istnieje jedna fundamentalna różnica w tej analogii: jedno wiązanie ma miejsce w czasie wykonywania (dla zamknięć), a drugie w czasie kompilacji (dla typów zależnych od ścieżki).
jhegedus