这个问题之前可能会被提出并回答,但我想通过一个例子来理解这个问题,我无法推断出Aux模式可能有用的地方!所以这是特征:
trait Foo[A] {
type B
def value: B
}
为什么我有一个类型绑定到值函数的返回类型?我这样做了什么?特别是,我会在哪里使用这种模式?
这个问题之前可能会被提出并回答,但我想通过一个例子来理解这个问题,我无法推断出Aux模式可能有用的地方!所以这是特征:
trait Foo[A] {
type B
def value: B
}
为什么我有一个类型绑定到值函数的返回类型?我这样做了什么?特别是,我会在哪里使用这种模式?
想象一下类型类获取任何元组的最后一个元素。
trait Last[A] {
type B
def last(a: A): B
}
object Last {
type Aux[A,B0] = Last[A] { type B = B0 }
implicit def tuple1Last[A]: Aux[Tuple1[A],A] = new Last[Tuple1[A]] {
type B = A
def last(a: Tuple1[A]) = a._1
}
implicit def tuple2Last[A,C]: Aux[(A,C),C] = new Last[(A,C)] {
type B = C
def last(a: (A,C)) = a._2
}
...
}
方式 B
总是取决于类型 A
, 这就是为什么 A
是类型类的输入类型 B
是输出类型。
现在,如果你想要一个可以根据你需要访问的最后一个元素对任何元组列表进行排序的函数 B
输入相同的参数列表。这是斯卡拉目前状态下的主要原因,为什么你需要这个 Aux
模式:目前无法参考 last.B
键入与where相同的参数列表 last
已定义,也不可能有多个隐式参数列表。
def sort[A,B](l: List[A])(implicit last: Last.Aux[A,B], ord: Ordering[B]) = ???
当然你总是可以写 Last[A] { type B = B0 }
完全没有,但很明显这很快变得非常不切实际(想象一下,使用依赖类型添加几个隐含参数,这对于Shapeless非常常见);那就是 Aux
类型别名进来。