问题描述
我对 Aux 模式(如在 shapeless 和其他地方使用)有一些了解,其中将类型成员提取到类型参数中,并且我知道这是一种解决方法,因为同一参数列表中的参数可以不相互依赖——但我一般不清楚它的用途和解决什么问题.
I have a bit of a sense of the Aux pattern (as used in shapeless and elsewhere) in which a type member is extracted into a type parameter, and I know it's a workaround the fact that arguments in the same argument list can't depend on each other -- but I'm not clear generally what it's used for and what problems it solves.
例如,我目前正在尝试弄清楚如何保留和使用白盒宏返回的更具体的类型——这是 Aux 的用例吗?
For example, I'm currently trying to figure out how to preserve and work with the more specific type returned by a whitebox macro -- is this a usecase for Aux?
有简单的描述吗?
推荐答案
简单地说,这种模式可以让您在两个泛型类型参数之间建立关系.
Simply speaking this pattern lets you establish a relation between two generic type parameters.
让我们看一下 shapeless 的 LabelledGeneric
类型类,它为案例类提供了一个通用的 HList
表示:
Let's take a look at shapeless' LabelledGeneric
type class which gives you a generic HList
representation for case classes:
trait LabelledGeneric[T] {
type Repr
}
T
是输入类型,即 LabelledGeneric[MyCaseClass]
将为您提供 MyCaseClass
的 HList 表示.Repr
为输出类型,即T
对应的HList类型.
T
is the input type, i.e LabelledGeneric[MyCaseClass]
will give you the HList representation of MyCaseClass
. Repr
is the output type, i.e. the HList type corresponding to T
.
让我们编写一个接受 Generic
实例并需要输出类型的另一个参数的方法.例如,我们可以使用 Keys
来收集标记泛型的字段名称
Let's write a method that takes a Generic
instance and needs another parameter of the output type. For instance we could use Keys
to collect the field names of a labelled generic
def fieldNames[T](implicit gen: LabelledGeneric[T], keys: Keys[gen.Repr]): keys.Repr …
除非这不起作用,因为 Scala 不允许您在此处访问 gen
或 keys
.我们可以有一个具体的类型或一个类型变量.
Except that this doesn't work because Scala doesn't let you access gen
or keys
here. We can either have a concrete type or a type variable.
这就是 Aux 发挥作用的地方:它让我们提升"gen.Repr
到一个类型变量中:
And that's where Aux comes into play: It let's us "lift" gen.Repr
into a type variable:
object Generic {
type Aux[T, Repr0] = Generic[T] { type Repr = Repr0 }
}
如您所见,Aux
类型为我们提供了从 Repr
到类型变量的方法,因此我们最终可以定义 foo
:
As you can see the Aux
type gives us a way from Repr
to a 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 …
如果您熟悉 Prolog,您可以将 Aux 视为证明两个类型变量之间关系的谓词.在上面的示例中,您可以将其读作LabelledGeneric 证明 Repr
是标签为 T 的泛型表示,而 Keys.Aux 证明 K 是 Repr 的所有键的列表".
If you are familiar with Prolog you can read Aux as a predicate that proves a relation between two type variables. In the above example you can read it as "LabelledGeneric proves that Repr
is the generic representation with labels of T, and Keys.Aux proves that K is a list of all keys of Repr".
这篇关于Aux 模式在 Scala 中完成了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!