这个问题之前可能会被提出并回答,但我想通过一个例子来理解这个问题,我无法推断出Aux模式可能有用的地方!所以这是特征:
trait Foo[A] {
type B
def value: B
}
Run Code Online (Sandbox Code Playgroud)
为什么我有一个类型绑定到值函数的返回类型?我这样做了什么?特别是,我会在哪里使用这种模式?
Jas*_*r-M 14
想象一下类型类获取任何元组的最后一个元素.
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
}
...
}
Run Code Online (Sandbox Code Playgroud)
类型B总是取决于类型A,这就是为什么A是类型类的输入类型并且B是输出类型.
现在,如果您想要一个可以根据最后一个元素对任何元组列表进行排序的函数,则需要访问B同一参数列表中的类型.在Scala的当前状态中,这就是为什么需要Aux模式的主要原因:目前不可能在定义的位置引用last.B相同参数列表中的类型last,也不可能有多个隐式参数列表.
def sort[A,B](as: List[A])(implicit last: Last.Aux[A,B], ord: Ordering[B]) = as.sortBy(last.last)
Run Code Online (Sandbox Code Playgroud)
当然你总是可以Last[A] { type B = B0 }完全写出来,但显然这很快变得非常不切实际(想象一下,在依赖类型中增加一些隐含的参数,这与Shapeless非常相似); 这就是Aux类型别名的来源.
Mar*_*lic 12
在同一个参数列表中支持启动 Scala 3依赖类型,这似乎使模式变得不必要,例如,Jasper-M 的代码段简化为Aux
trait Last[A]:
type B
def last(a: A): B
given [A]: Last[Tuple1[A]] with
type B = A
def last(a: Tuple1[A]) = a._1
given [A, C]: Last[(A,C)] with
type B = C
def last(a: (A,C)) = a._2
def sort[A](as: List[A])(using last: Last[A], ord: Ordering[last.B]) = as.sortBy(last.last)
sort(List(("ffle",3), ("fu",2), ("ker",1)))
// List((ker,1), (fu,2), (ffle,3))
Run Code Online (Sandbox Code Playgroud)
注意last.Bwhere lastis a value的用法来自同一个参数列表
def sort[A](as: List[A])(using last: Last[A], ord: Ordering[last.B])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1356 次 |
| 最近记录: |