Simply put, this template allows you to establish a relationship between two parameters of a typical type.
Let's look at a shapeless class like LabelledGeneric , which gives you a general overview of the HList for case classes:
trait LabelledGeneric[T] { type Repr }
T is the type of input, i.e. LabelledGeneric[MyCaseClass] will provide you with an HList MyCaseClass . Repr is the output type, that is, the HList type corresponding to T
Suppose you write a method that accepts a Generic instance and needs another output type parameter. For example, we could use Keys to collect field names of a marked common
def fieldNames[T](implicit gen: LabelledGeneric[T], keys: Keys[gen.Repr]): keys.Repr β¦
Except this does not work because Scala does not allow you to access gen or Keys here. We can either have a specific type or a type variable.
And the fact that Aux plays the game: it allows you to "raise" gen.Repr into a variable of the type:
object Generic { type Aux[T, Repr0] = Generic[T] { type Repr = Repr0 } }
As you can see, the Aux type gives us the path from Repr to the type variable, so we can finally define foo :
def foo[T, Repr, K]( implicit gen: LabelledGeneric.Aux[T, Repr], keys: Keys.Aux[Repr, K] ): K β¦
If you are familiar with Prolog, you can read Aux as a predicate that proves the relationship between two type variables. In the above example, you can read it as "LabelledGeneric" proves that Repr is a generic representation with T labels, and Keys.Aux proves that K is a list of all Repr keys. "