在Scala中Aux模式实现了什么?

时间:2016-07-23 11:30:44

标签: scala typeclass shapeless scala-macros

我有点了解Aux模式(在无形和其他地方使用),其中一个类型成员被提取到一个类型参数中,我知道这是一个解决方法,即同一参数列表中的参数可以彼此依赖 - 但我一般不清楚它用于什么以及它解决了什么问题。

例如,我目前正试图弄清楚如何保存和使用whitebox宏返回的更具体的类型 - 这是Aux的用例吗?

有简单的描述吗?

1 个答案:

答案 0 :(得分:8)

简单地说,这种模式可以让你建立两个泛型类型参数之间的关系。

让我们看看无形的'LabelledGeneric类型类,它为您提供案例类的通用HList表示形式:

trait LabelledGeneric[T] {
  type Repr
}

T是输入类型,即LabelledGeneric[MyCaseClass]将为您提供MyCaseClass的HList表示。 Repr是输出类型,即与T对应的HList类型。

让我们编写一个采用Generic实例并需要输出类型的另一个参数的方法。例如,我们可以使用Keys来收集带标签的通用

的字段名称
def fieldNames[T](implicit gen: LabelledGeneric[T], keys: Keys[gen.Repr]): keys.Repr …

除非这不起作用,因为Scala不允许您在此处访问genkeys。我们可以有一个具体类型或类型变量。

这就是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 …

如果你熟悉Prolog,你可以阅读Aux作为证明两个类型变量之间关系的谓词。在上面的示例中,您可以将其读作“LabelledGeneric证明Repr是标签为T的通用表示,而Keys.Aux证明K是Repr的所有键的列表。”