见证类型推导问题
Witness type derivation issue
我想构建从案例 类 中删除字段的通用解决方案。
使用这个 我构建了这个工作代码:
implicit class SemiGenericIgnoringOps[T](t: T) {
def ignoring[TRepr <: HList,
V,
TargetRepr <: HList,
H <: HList](k: Witness)
(implicit
gen: LabelledGeneric.Aux[T, TRepr],
rem: Remover.Aux[TRepr, k.T, (V, TargetRepr)],
upd: Updater.Aux[TargetRepr, FieldType[k.T, V], H],
ali: Align[H, TRepr]
): SemiGeneric.Aux[T, TargetRepr] = new SemiGeneric[T] {
type Repr = TargetRepr
def convert: TargetRepr = gen.to(t) - k
}
}
我想用 Witness
中的 HList
替换单个 k: Witness
。但即使添加通用 Witness
类型参数也会导致编译错误:找不到 Remover
.
的隐式值
implicit class SemiGenericIgnoringOps[T](t: T) {
def ignoring[TRepr <: HList,
V,
TargetRepr <: HList,
H <: HList,
W <: Witness](w: W) // added type parameter
(implicit
gen: LabelledGeneric.Aux[T, TRepr],
rem: Remover.Aux[TRepr, w.T, (V, TargetRepr)],
upd: Updater.Aux[TargetRepr, FieldType[w.T, V], H],
ali: Align[H, TRepr]
): SemiGeneric.Aux[T, TargetRepr] = new SemiGeneric[T] {
type Repr = TargetRepr
def convert: TargetRepr = gen.to(t) - w
}
}
似乎编译器无法导出Witness.T
。 Witness.Aux[R]
的把戏无济于事。如何克服这个问题?
与您提到的答案相反,您不需要 Updater
和 Align
,因为您的 convert
与 HList
/ 记录一起使用。
以下代码有效:
import shapeless.ops.record.Remover
import shapeless.{::, HList, HNil, LabelledGeneric, Witness}
trait GenericAllKeysRemover[A <: Product, K <: HList] {
type Out <: HList
def apply(a: A): Out
}
object GenericAllKeysRemover {
type Aux[A <: Product, K <: HList, Out0 <: HList] = GenericAllKeysRemover[A, K] { type Out = Out0 }
def instance[A <: Product, K <: HList, Out0 <: HList](f: A => Out0): Aux[A, K, Out0] = new GenericAllKeysRemover[A, K] {
override type Out = Out0
override def apply(a: A): Out = f(a)
}
def apply[A <: Product, K <: HList](implicit genericAllKeysRemover: GenericAllKeysRemover[A, K]): Aux[A, K, genericAllKeysRemover.Out] = genericAllKeysRemover
implicit def mkGenericAllKeysRemover[A <: Product, L <: HList, K <: HList, Out <: HList](implicit
labelledGeneric: LabelledGeneric.Aux[A, L],
allKeysRemover: AllKeysRemover.Aux[L, K, Out]): Aux[A, K, Out] =
instance(a => allKeysRemover(labelledGeneric.to(a)))
}
trait AllKeysRemover[L <: HList, K <: HList] {
type Out <: HList
def apply(l: L): Out
}
object AllKeysRemover {
type Aux[L <: HList, K <: HList, Out0 <: HList] = AllKeysRemover[L, K] { type Out = Out0 }
def instance[L <: HList, K <: HList, Out0 <: HList](f: L => Out0): Aux[L, K, Out0] = new AllKeysRemover[L, K] {
override type Out = Out0
override def apply(l: L): Out0 = f(l)
}
def apply[L <: HList, K <: HList](implicit allKeysRemover: AllKeysRemover[L, K]): Aux[L, K, allKeysRemover.Out] =
allKeysRemover
implicit def mkAllKeysRemover[L <: HList]: Aux[L, HNil, L] = instance(identity)
implicit def mkAllKeysRemover1[L <: HList, H, T <: HList, V, L_removeH <: HList, Out <: HList](implicit
remover: Remover.Aux[L, H, (V, L_removeH)],
allKeysRemover: Aux[L_removeH, T, Out]): Aux[L, H :: T, Out] =
instance(l => allKeysRemover(remover(l)._2))
}
case class MyClass(i: Int, s: String, b: Boolean)
GenericAllKeysRemover[MyClass, Witness.`'s`.T :: Witness.`'b`.T :: HNil].apply(MyClass(1, "a", true)) //1 :: HNil
我想构建从案例 类 中删除字段的通用解决方案。
使用这个
implicit class SemiGenericIgnoringOps[T](t: T) {
def ignoring[TRepr <: HList,
V,
TargetRepr <: HList,
H <: HList](k: Witness)
(implicit
gen: LabelledGeneric.Aux[T, TRepr],
rem: Remover.Aux[TRepr, k.T, (V, TargetRepr)],
upd: Updater.Aux[TargetRepr, FieldType[k.T, V], H],
ali: Align[H, TRepr]
): SemiGeneric.Aux[T, TargetRepr] = new SemiGeneric[T] {
type Repr = TargetRepr
def convert: TargetRepr = gen.to(t) - k
}
}
我想用 Witness
中的 HList
替换单个 k: Witness
。但即使添加通用 Witness
类型参数也会导致编译错误:找不到 Remover
.
implicit class SemiGenericIgnoringOps[T](t: T) {
def ignoring[TRepr <: HList,
V,
TargetRepr <: HList,
H <: HList,
W <: Witness](w: W) // added type parameter
(implicit
gen: LabelledGeneric.Aux[T, TRepr],
rem: Remover.Aux[TRepr, w.T, (V, TargetRepr)],
upd: Updater.Aux[TargetRepr, FieldType[w.T, V], H],
ali: Align[H, TRepr]
): SemiGeneric.Aux[T, TargetRepr] = new SemiGeneric[T] {
type Repr = TargetRepr
def convert: TargetRepr = gen.to(t) - w
}
}
似乎编译器无法导出Witness.T
。 Witness.Aux[R]
的把戏无济于事。如何克服这个问题?
与您提到的答案相反,您不需要 Updater
和 Align
,因为您的 convert
与 HList
/ 记录一起使用。
以下代码有效:
import shapeless.ops.record.Remover
import shapeless.{::, HList, HNil, LabelledGeneric, Witness}
trait GenericAllKeysRemover[A <: Product, K <: HList] {
type Out <: HList
def apply(a: A): Out
}
object GenericAllKeysRemover {
type Aux[A <: Product, K <: HList, Out0 <: HList] = GenericAllKeysRemover[A, K] { type Out = Out0 }
def instance[A <: Product, K <: HList, Out0 <: HList](f: A => Out0): Aux[A, K, Out0] = new GenericAllKeysRemover[A, K] {
override type Out = Out0
override def apply(a: A): Out = f(a)
}
def apply[A <: Product, K <: HList](implicit genericAllKeysRemover: GenericAllKeysRemover[A, K]): Aux[A, K, genericAllKeysRemover.Out] = genericAllKeysRemover
implicit def mkGenericAllKeysRemover[A <: Product, L <: HList, K <: HList, Out <: HList](implicit
labelledGeneric: LabelledGeneric.Aux[A, L],
allKeysRemover: AllKeysRemover.Aux[L, K, Out]): Aux[A, K, Out] =
instance(a => allKeysRemover(labelledGeneric.to(a)))
}
trait AllKeysRemover[L <: HList, K <: HList] {
type Out <: HList
def apply(l: L): Out
}
object AllKeysRemover {
type Aux[L <: HList, K <: HList, Out0 <: HList] = AllKeysRemover[L, K] { type Out = Out0 }
def instance[L <: HList, K <: HList, Out0 <: HList](f: L => Out0): Aux[L, K, Out0] = new AllKeysRemover[L, K] {
override type Out = Out0
override def apply(l: L): Out0 = f(l)
}
def apply[L <: HList, K <: HList](implicit allKeysRemover: AllKeysRemover[L, K]): Aux[L, K, allKeysRemover.Out] =
allKeysRemover
implicit def mkAllKeysRemover[L <: HList]: Aux[L, HNil, L] = instance(identity)
implicit def mkAllKeysRemover1[L <: HList, H, T <: HList, V, L_removeH <: HList, Out <: HList](implicit
remover: Remover.Aux[L, H, (V, L_removeH)],
allKeysRemover: Aux[L_removeH, T, Out]): Aux[L, H :: T, Out] =
instance(l => allKeysRemover(remover(l)._2))
}
case class MyClass(i: Int, s: String, b: Boolean)
GenericAllKeysRemover[MyClass, Witness.`'s`.T :: Witness.`'b`.T :: HNil].apply(MyClass(1, "a", true)) //1 :: HNil