Vereinfacht ausgedrückt können Sie mit diesem Muster eine Beziehung zwischen zwei generischen Typparametern herstellen.
Lassen Sie uns LabelledGeneric
Typklasse einen Blick auf formlos nehmen, der Sie eine generische HList
Darstellung für Fallklassen gibt:
trait LabelledGeneric[T] {
type Repr
}
T
ist der Eingabetyp, das heißt LabelledGeneric[MyCaseClass]
geben Ihnen die hList Darstellung MyCaseClass
. Repr
ist der Ausgabetyp, d. H. Der HList-Typ, der T
entspricht.
Lassen Sie uns eine Methode schreiben, die eine Generic
Instanz benötigt und einen anderen Parameter des Ausgabetyps benötigt. Zum Beispiel könnten wir Keys
verwenden, um die Feldnamen eines markierten generic
def fieldNames[T](implicit gen: LabelledGeneric[T], keys: Keys[gen.Repr]): keys.Repr …
Außer zu sammeln, dass dies nicht funktioniert, weil Scala Sie hier zugreifen gen
oder keys
nicht nachlässt. Wir können entweder einen konkreten Typ oder eine Typvariable haben.
Und das ist, wo Aux ins Spiel kommt: Es läßt sie uns „Lift“ gen.Repr
in eine Variable vom Typ:
object Generic {
type Aux[T, Repr0] = Generic[T] { type Repr = Repr0 }
}
Wie Sie den Aux
Typ gibt uns einen Weg aus Repr
auf eine Variable vom Typ sehen können, so wir können foo
endlich definieren:
def foo[T, Repr, K](
implicit gen: LabelledGeneric.Aux[T, Repr],
keys: Keys.Aux[Repr, K]
): K …
Wenn Sie mit Prolog vertraut sind, können Sie Aux als Prädikat lesen, die beweist, eine Beziehung zwischen zwei Typvariablen. Im obigen Beispiel können Sie es lesen, wie "LabelledGeneric beweist, dass Repr
die generische Darstellung mit Beschriftungen von T ist, und Keys.Aux beweist, dass K eine Liste aller Schlüssel von Repr ist".
Siehe meine Antwort [hier] (http://Stackoverflow.com/a/34548518/334519) für einige Diskussion. –