2016-07-23 15 views
5

Ich habe ein wenig Sinn für das Aux-Muster (wie in Shapeless und anderswo verwendet), in denen ein Typ-Member in einen Typparameter extrahiert wird, und ich weiß, es ist eine Umgehung der Tatsache, dass Argumente in der gleichen Argumentliste können Sie hängen voneinander ab - aber ich bin mir nicht sicher, wofür es verwendet wird und welche Probleme es löst.Was bewirkt das Aux-Muster in Scala?

Zum Beispiel versuche ich gerade herauszufinden, wie man mit dem spezifischeren Typ, der von einem Whitebox-Makro zurückgegeben wird, arbeitet und arbeitet - ist das ein Anwendungsfall für Aux?

Gibt es eine einfache Beschreibung?

+0

Siehe meine Antwort [hier] (http://Stackoverflow.com/a/34548518/334519) für einige Diskussion. –

Antwort

5

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".