Aux 模式在 Scala 中完成了什么? [英] What does the Aux pattern accomplish in Scala?

查看:89
本文介绍了Aux 模式在 Scala 中完成了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 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 不允许您在此处访问 genkeys.我们可以有一个具体的类型或一个类型变量.

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 中完成了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆