Po prostu ten wzorzec pozwala ustalić związek między dwoma rodzajowymi parametrami.
Rzućmy okiem na bezkształtną klasy LabelledGeneric
typu co daje ogólny HList
reprezentacji dla klas przypadków:
trait LabelledGeneric[T] {
type Repr
}
T
jest typ wejścia, tj LabelledGeneric[MyCaseClass]
daje reprezentację HList z MyCaseClass
. Repr
to typ wyjściowy, tj. Typ HList odpowiadający T
.
Napiszmy metodę, która wymaga instancji Generic
i potrzebuje innego parametru typu wyjściowego. Na przykład możemy użyć Keys
do zbierania nazw pól znakowanego generycznego
def fieldNames[T](implicit gen: LabelledGeneric[T], keys: Keys[gen.Repr]): keys.Repr …
Tyle tylko, że to nie działa, ponieważ Scala nie pozwala na dostęp gen
lub keys
tutaj. Możemy mieć zmienną typu konkretnego lub typu.
I tam Aux wchodzi w grę: To niech nas „lift” gen.Repr
do zmiennej typu:
object Generic {
type Aux[T, Repr0] = Generic[T] { type Repr = Repr0 }
}
Jak można zobaczyć rodzaj Aux
daje nam drogę od Repr
do zmiennej typu, więc możemy wreszcie określić foo
:
def foo[T, Repr, K](
implicit gen: LabelledGeneric.Aux[T, Repr],
keys: Keys.Aux[Repr, K]
): K …
Jeśli jesteś zaznajomiony z Prologu można przeczytać Aux jako orzecznik że udowodni relacja między dwoma zmiennymi typu. W powyższym przykładzie możesz przeczytać: "LabelledGeneric udowadnia, że Repr
jest ogólną reprezentacją z etykietami T, a Keys.Aux udowadnia, że K jest listą wszystkich kluczy Repr".
Zobacz moją odpowiedź [tutaj] (http://stackoverflow.com/a/34548518/334519) w celu omówienia. –