隐式参数优先级
Implicit parameter precedence
我正在尝试将泛型类型转换为 HList:
trait ToHList[T] {
type Out <: HList
def apply(value: T): Out
}
trait LowPriorityToHList {
implicit def default[T]: ToHList.Aux[T, T :: HNil] =
new ToHList[T] {
override type Out = T :: HNil
override def apply(value: T): T :: HNil = value :: HNil
}
}
object ToHList extends LowPriorityToHList {
type Aux[T, Out0] = ToHList[T] { type Out = Out0 }
def apply[T](implicit toHList: ToHList[T]): Aux[T, toHList.Out] = toHList
implicit def toHList[T, Repr <: HList, N <: Nat](implicit
gen: Generic.Aux[T, Repr],
len: Length.Aux[Repr, N],
lt: LT[Nat._0, N]): ToHList.Aux[T, Repr] =
new ToHList[T] {
override type Out = Repr
override def apply(value: T): Repr = gen.to(value)
}
}
object Main extends App {
println(ToHList.apply[Int].apply(1)) // expected 1 :: HNil
println(ToHList.apply[(Int, Int)].apply((1, 2))) // expected 1 :: 2 :: HNil
}
我打算让 ToHList.toHList
优先于 ToHList.default
但是
此代码导致以下编译错误:
[error] ToHList.scala:39:24: ambiguous implicit values:
[error] both method toHList in object ToHList of type [T, Repr <: shapeless.HList, N <: shapeless.Nat](implicit gen: shapeless.Generic.Aux[T,Repr], implicit len: shapeless.ops.hlist.Length.Aux[Repr,N], implicit lt: shapeless.ops.nat.LT[shapeless.Nat._0,N])ToHList.Aux[T,Repr]
[error] and method default in trait LowPriorityToHList of type [T]=> ToHList.Aux[T,T :: shapeless.HNil]
[error] match expected type ToHList[(Int, Int)]
[error] println(ToHList.apply[(Int, Int)].apply((1, 2))) // expected 1 :: 2 :: HNil
我想 ToHList.toHList
优先于 ToHList.default
。
我该如何解决这个错误?
如果toHList
和default
都适用,则它们具有相同的优先级,因此它们会产生歧义。事实上,虽然 default
被定义在一个低优先级的超级特征中,但它比 toHList
更具体。请参阅
中的详细信息
所以没有理由将default
放入低优先级的超级特质中,这不会产生预期的效果。但是,如果将 toHList
和 default
放入同一个对象中,default
将赢得更具体。从 expected 1 :: 2 :: HNil
来看,你似乎希望反之亦然 toHList
获胜。您可以使用 shapeless.LowPriority
object ToHList {
type Aux[T, Out0] = ToHList[T] { type Out = Out0 }
def apply[T](implicit toHList: ToHList[T]): Aux[T, toHList.Out] = toHList
implicit def toHList[T, Repr <: HList, N <: Nat](implicit
gen: Generic.Aux[T, Repr],
len: Length.Aux[Repr, N],
lt: LT[Nat._0, N]
): ToHList.Aux[T, Repr] =
new ToHList[T] {
override type Out = Repr
override def apply(value: T): Repr = gen.to(value)
}
implicit def default[T](implicit
lowPriority: LowPriority
): ToHList.Aux[T, T :: HNil] =
new ToHList[T] {
override type Out = T :: HNil
override def apply(value: T): T :: HNil = value :: HNil
}
}
或者在这种特定情况下,您可以使用 shapeless.Refute
、shapeless.OrElse
implicit def default[T](implicit
orElse: OrElse[Refute[Generic[T]], Generic.Aux[T, HNil]]
): ToHList.Aux[T, T :: HNil] =
new ToHList[T] {
override type Out = T :: HNil
override def apply(value: T): T :: HNil = value :: HNil
}
我正在尝试将泛型类型转换为 HList:
trait ToHList[T] {
type Out <: HList
def apply(value: T): Out
}
trait LowPriorityToHList {
implicit def default[T]: ToHList.Aux[T, T :: HNil] =
new ToHList[T] {
override type Out = T :: HNil
override def apply(value: T): T :: HNil = value :: HNil
}
}
object ToHList extends LowPriorityToHList {
type Aux[T, Out0] = ToHList[T] { type Out = Out0 }
def apply[T](implicit toHList: ToHList[T]): Aux[T, toHList.Out] = toHList
implicit def toHList[T, Repr <: HList, N <: Nat](implicit
gen: Generic.Aux[T, Repr],
len: Length.Aux[Repr, N],
lt: LT[Nat._0, N]): ToHList.Aux[T, Repr] =
new ToHList[T] {
override type Out = Repr
override def apply(value: T): Repr = gen.to(value)
}
}
object Main extends App {
println(ToHList.apply[Int].apply(1)) // expected 1 :: HNil
println(ToHList.apply[(Int, Int)].apply((1, 2))) // expected 1 :: 2 :: HNil
}
我打算让 ToHList.toHList
优先于 ToHList.default
但是
此代码导致以下编译错误:
[error] ToHList.scala:39:24: ambiguous implicit values:
[error] both method toHList in object ToHList of type [T, Repr <: shapeless.HList, N <: shapeless.Nat](implicit gen: shapeless.Generic.Aux[T,Repr], implicit len: shapeless.ops.hlist.Length.Aux[Repr,N], implicit lt: shapeless.ops.nat.LT[shapeless.Nat._0,N])ToHList.Aux[T,Repr]
[error] and method default in trait LowPriorityToHList of type [T]=> ToHList.Aux[T,T :: shapeless.HNil]
[error] match expected type ToHList[(Int, Int)]
[error] println(ToHList.apply[(Int, Int)].apply((1, 2))) // expected 1 :: 2 :: HNil
我想 ToHList.toHList
优先于 ToHList.default
。
我该如何解决这个错误?
如果toHList
和default
都适用,则它们具有相同的优先级,因此它们会产生歧义。事实上,虽然 default
被定义在一个低优先级的超级特征中,但它比 toHList
更具体。请参阅
所以没有理由将default
放入低优先级的超级特质中,这不会产生预期的效果。但是,如果将 toHList
和 default
放入同一个对象中,default
将赢得更具体。从 expected 1 :: 2 :: HNil
来看,你似乎希望反之亦然 toHList
获胜。您可以使用 shapeless.LowPriority
object ToHList {
type Aux[T, Out0] = ToHList[T] { type Out = Out0 }
def apply[T](implicit toHList: ToHList[T]): Aux[T, toHList.Out] = toHList
implicit def toHList[T, Repr <: HList, N <: Nat](implicit
gen: Generic.Aux[T, Repr],
len: Length.Aux[Repr, N],
lt: LT[Nat._0, N]
): ToHList.Aux[T, Repr] =
new ToHList[T] {
override type Out = Repr
override def apply(value: T): Repr = gen.to(value)
}
implicit def default[T](implicit
lowPriority: LowPriority
): ToHList.Aux[T, T :: HNil] =
new ToHList[T] {
override type Out = T :: HNil
override def apply(value: T): T :: HNil = value :: HNil
}
}
或者在这种特定情况下,您可以使用 shapeless.Refute
、shapeless.OrElse
implicit def default[T](implicit
orElse: OrElse[Refute[Generic[T]], Generic.Aux[T, HNil]]
): ToHList.Aux[T, T :: HNil] =
new ToHList[T] {
override type Out = T :: HNil
override def apply(value: T): T :: HNil = value :: HNil
}