Проще говоря, этот шаблон позволяет установить связь между двумя параметрами типового типа.
Давайте посмотрим на бесформенном классе LabelledGeneric
типа, который дает вам общее HList
представление для тематических классов:
trait LabelledGeneric[T] {
type Repr
}
T
типа входного сигнала, т.е. LabelledGeneric[MyCaseClass]
даст вам HList представление MyCaseClass
. Repr
- тип выходного сигнала, то есть тип HList, соответствующий T
.
Давайте напишем метод, который принимает экземпляр Generic
и нуждается в другом параметре типа вывода. Например, мы могли бы использовать Keys
собрать имена полей помеченного общего
def fieldNames[T](implicit gen: LabelledGeneric[T], keys: Keys[gen.Repr]): keys.Repr …
Кроме того, что это не работает, потому что Scala не позволяет получить доступ к gen
или keys
здесь. Мы можем либо иметь конкретный тип, либо переменную типа.
И вот где Aux входит в игру: Это давайте нам «поднять» gen.Repr
в переменную типа:
object Generic {
type Aux[T, Repr0] = Generic[T] { type Repr = Repr0 }
}
Как вы можете видеть Aux
тип дает нам путь от Repr
к переменной типа, так мы можем, наконец, определить foo
:
def foo[T, Repr, K](
implicit gen: LabelledGeneric.Aux[T, Repr],
keys: Keys.Aux[Repr, K]
): K …
Если вы знакомы с Прологом вы можете прочитать Aux как предикат, который доказывает связь между двумя переменными типа. В приведенном выше примере вы можете прочитать его как «LabelledGeneric» доказывает, что Repr
является общим представлением с метками T, а Keys.Aux доказывает, что K является списком всех ключей Repr ».
См. Мой ответ [здесь] (http://stackoverflow.com/a/34548518/334519) для обсуждения. –