Shapeless LabelledGeneric, но игнорирует некоторые поля
Я хотел бы определить бесформенный LabelledGeneric
игнорирует одно (или несколько) полей при конвертации в HList
; при преобразовании HList
обратно это должно заменить пользовательское значение. Цель состоит в том, чтобы иметь возможность написать что-то вроде этого:
case class Foo(i: Int, s: String)
val foo = Foo(123, "Hello")
val gen = LabelledGeneric[Foo].ignoring('i)(defaultValue = -1)
val hlist = gen.to(foo)
// "Hello" :: HNil
val foo2 = gen.from(hlist)
assert(foo2 == Foo(-1, "Hello"))
Это то, что я до сих пор. Он компилируется, но я не могу заставить типы правильно выстраиваться для неявного разрешения, когда пытаюсь его использовать:
implicit class IgnoringOps[T](orig: LabelledGeneric[T]) {
def ignoring[Orig <: HList, V, Ign <: HList](k: Witness)(defaultValue: V)(implicit
gen: LabelledGeneric.Aux[T, Orig],
rem: Remover.Aux[Orig, FieldType[k.T, V], Ign],
upd: Updater.Aux[Ign, FieldType[k.T, V], Orig]): LabelledGeneric[T] = {
new LabelledGeneric[T] {
override type Repr = Ign
override def to(t: T): Ign = rem(gen.to(t))
override def from(r: Ign): T = gen.from(upd(r, field[k.T](defaultValue)))
}
}
}
Может кто-нибудь пролить свет на то, что я делаю неправильно?
1 ответ
Решение
Это должно работать как задумано (согласно вашему примеру):
implicit class IgnoringOps[T, L <: HList](gen: LabelledGeneric.Aux[T, L]) {
def ignoring[V, I <: HList, H <: HList](k: Witness)(v: V)(implicit
rem: Remover.Aux[L, k.T, (V, I)],
upd: Updater.Aux[I, FieldType[k.T, V], H],
ali: Align[H, L]
): LabelledGeneric[T] = new LabelledGeneric[T] {
override type Repr = I
//`rem` is implicitly used there
override def to(t: T): I = gen.to(t) - k
//`upd` and `ali` are implicitly used there
override def from(r: I): T = gen.from(r + field[k.T](v))
}
}
Заметки:
- Удален неявный параметр
gen: LabelledGeneric.Aux[T, L]
отignoring
Вы можете использовать неявный параметр классаorig
; - Используемый
-
а также+
методы изRecordOps
вместо использования явноrem
а такжеupd
; - обновленный
rem
неявный параметр изRemover.Aux[L, FieldType[k.T, V], I],
вRemover.Aux[L, k.T, (V, I)]
; - Добавлен промежуточный помощник
H <: HList
; - обновленный
upd
неявный параметр, используя вышеупомянутый промежуточный помощник, изUpdater.Aux[I, FieldType[k.T, V], L]
вUpdater.Aux[I, FieldType[k.T, V], H]
; - добавленной
ali
неявно прося выравниванияH
а такжеL
:ali: Align[H, L]