编写一个类型类,选择依赖于上下文绑定
Writing a typeclass with selection dependent on context bound
我的初始代码:
sealed trait Adder[L <: HList, U] extends DepFn2[L, Vector[U]]
object Adder {
def apply[L <: HList, U: Ordering](implicit adder: Adder[L, U]): Aux[L, U, adder.Out] = adder
type Aux[L <: HList, U, Out0] = Adder[L, U] { type Out = Out0 }
implicit def found[T <: HList, U: Ordering]: Aux[Vector[U] :: T, U, Vector[U] :: T] =
new Adder[Vector[U] :: T, U] {
type Out = Vector[U] :: T
def apply(l: Vector[U] :: T, collection: Vector[U]): Out = {
(l.head ++ collection).sorted :: l.tail
}
}
implicit def notFound[H, T <: HList, U: Ordering, OutT <: HList](implicit ut: Aux[T, U, OutT]): Aux[H :: T, U, H :: OutT] =
new Adder[H :: T, U] {
type Out = H :: OutT
def apply(l: H :: T, collection: Vector[U]): Out = {
val outT = ut(l.tail, collection)
l.head :: outT
}
}
implicit def empty[U: Ordering]: Aux[HNil, U, Vector[U] :: HNil] =
new Adder[HNil, U] {
type Out = Vector[U] :: HNil
def apply(l: HNil, collection: Vector[U]): Out = collection :: HNil
}
}
我发现了一个没有上下文绑定的错误
Ordering
,类型通过 notFound
而不是 found
传递,
这在事后看来并不令人惊讶。我试图通过添加来修复错误
另一个隐式应该在没有 Ordering
:
时触发
implicit def foundNoOrdering[T <: HList, U]: Aux[Vector[U] :: T, U, Vector[U] :: T] =
new Adder[Vector[U] :: T, U] {
type Out = Vector[U] :: T
def apply(l: Vector[U] :: T, collection: Vector[U]): Out = {
l.head ++ collection :: l.tail
}
}
但是,这会导致
foundNoOrdering
和 found
。我怎样才能有不同的代码路径
取决于是否有 Ordering
?
标准技巧是通过将隐式放入祖先特征中来降低优先级
object Adder extends LowPriorityAdderImplicits {
implicit def found...
}
trait LowPriorityAdderImplicits {
implicit def foundNoOrdering....
}
您会在标准库中找到其中的一些。 LowPriorityImplicits这个名字好像习惯了。
在规范中:
- SLS §7.2 隐式参数
If there are several eligible arguments which match the implicit
parameter’s type, a most specific one will be chosen using the rules
of static overloading resolution (§6.26.3)
- SLS §6.26.3:相关位太长无法完整引用,但您有一些关于
A class or object C is derived from a class or object D if one of the
following holds:
• C is a subclass of D, or
• C is a companion object of a class derived from D, or
• D is a companion object of a class from which C is derived.
并且派生使其更具体并在解决方案中获得优先权。我相信其中一个只是为了隐含而制作的。
我的初始代码:
sealed trait Adder[L <: HList, U] extends DepFn2[L, Vector[U]]
object Adder {
def apply[L <: HList, U: Ordering](implicit adder: Adder[L, U]): Aux[L, U, adder.Out] = adder
type Aux[L <: HList, U, Out0] = Adder[L, U] { type Out = Out0 }
implicit def found[T <: HList, U: Ordering]: Aux[Vector[U] :: T, U, Vector[U] :: T] =
new Adder[Vector[U] :: T, U] {
type Out = Vector[U] :: T
def apply(l: Vector[U] :: T, collection: Vector[U]): Out = {
(l.head ++ collection).sorted :: l.tail
}
}
implicit def notFound[H, T <: HList, U: Ordering, OutT <: HList](implicit ut: Aux[T, U, OutT]): Aux[H :: T, U, H :: OutT] =
new Adder[H :: T, U] {
type Out = H :: OutT
def apply(l: H :: T, collection: Vector[U]): Out = {
val outT = ut(l.tail, collection)
l.head :: outT
}
}
implicit def empty[U: Ordering]: Aux[HNil, U, Vector[U] :: HNil] =
new Adder[HNil, U] {
type Out = Vector[U] :: HNil
def apply(l: HNil, collection: Vector[U]): Out = collection :: HNil
}
}
我发现了一个没有上下文绑定的错误
Ordering
,类型通过 notFound
而不是 found
传递,
这在事后看来并不令人惊讶。我试图通过添加来修复错误
另一个隐式应该在没有 Ordering
:
implicit def foundNoOrdering[T <: HList, U]: Aux[Vector[U] :: T, U, Vector[U] :: T] =
new Adder[Vector[U] :: T, U] {
type Out = Vector[U] :: T
def apply(l: Vector[U] :: T, collection: Vector[U]): Out = {
l.head ++ collection :: l.tail
}
}
但是,这会导致
foundNoOrdering
和 found
。我怎样才能有不同的代码路径
取决于是否有 Ordering
?
标准技巧是通过将隐式放入祖先特征中来降低优先级
object Adder extends LowPriorityAdderImplicits {
implicit def found...
}
trait LowPriorityAdderImplicits {
implicit def foundNoOrdering....
}
您会在标准库中找到其中的一些。 LowPriorityImplicits这个名字好像习惯了。
在规范中:
- SLS §7.2 隐式参数
If there are several eligible arguments which match the implicit parameter’s type, a most specific one will be chosen using the rules of static overloading resolution (§6.26.3)
- SLS §6.26.3:相关位太长无法完整引用,但您有一些关于
A class or object C is derived from a class or object D if one of the following holds:
• C is a subclass of D, or
• C is a companion object of a class derived from D, or
• D is a companion object of a class from which C is derived.
并且派生使其更具体并在解决方案中获得优先权。我相信其中一个只是为了隐含而制作的。