Кроме -Xlog-implicits
, еще один стандартный способ отладки последствий - это разрешение их вручную и просмотр ошибки компиляции.
Попробуйте
object Projection {
type Aux[A <: HList, K, V, B0 <: HList] = Projection[A, K, V] { type B = B0 }
type Key[K] = Symbol with Tagged[K]
type F[K, V] = FieldType[Key[K], V]
implicit def mkProjection[A <: HList, K, V, B0 <: HList](implicit
keyWitness: Witness.Aux[Key[K]],
updater: Updater.Aux[A, F[K, V], B0],
remover: Remover.Aux[B0, Key[K], (V, A)]
): Projection.Aux[A, K, V, B0] = new Projection[A, K, V] {
type B = B0
def from(b: B0): A = b - keyWitness
def to(a: A, v: V): B0 = a + field[Key[K]](v)
}
}
Затем
implicitly[Projection.Aux[HNil, "thirdField", Boolean, Record.`'thirdField -> Boolean`.T]]
компилируется.
Но хотя implicitly[thirdFieldWitness.T =:= "thirdField"]
implicitly[Projection.Aux[HNil, thirdFieldWitness.T, Boolean, Record.`'thirdField -> Boolean`.T]]
по-прежнему не компилируется. Но разрешенные вручную компиляции
implicitly[Projection.Aux[HNil,
thirdFieldWitness.T,
Boolean,
Record.`'thirdField -> Boolean`.T
]](Projection.mkProjection(
implicitly[Witness.Aux[Witness.`'thirdField`.T]],
implicitly[Updater.Aux[HNil, FieldType[Witness.`'thirdField`.T, Boolean], Record.`'thirdField -> Boolean`.T]],
implicitly[Remover.Aux[Record.`'thirdField -> Boolean`.T, Witness.`'thirdField`.T, (Boolean, HNil)]]
))
. Кажется, дело в том, что implicitly[Witness.Aux[Key["thirdField"]]]
компилируется, а implicitly[Witness.Aux[Key[thirdFieldWitness.T]]]
нет («Symbol with Tagged[thirdFieldWitness.T]
не является одноэлементным типом»).
Вы можете исправить компиляцию, добавив
implicit def extraWitness[S <: String](implicit
w: Witness.Aux[S]
): Witness.Aux[Symbol @@ S] = Witness.mkWitness(tag[S](Symbol(w.value)))
Я бы использовал стандартный API на основе символов
object Projection {
type Aux[A <: HList, K, V, B0 <: HList] = Projection[A, K, V] { type B = B0 }
type F[K, V] = FieldType[K, V]
implicit def mkProjection[A <: HList, K, V, B0 <: HList](implicit
keyWitness: Witness.Aux[K],
updater: Updater.Aux[A, F[K, V], B0],
remover: Remover.Aux[B0, K, (V, A)]
): Projection.Aux[A, K, V, B0] = new Projection[A, K, V] {
type B = B0
def from(b: B0): A = b - keyWitness
def to(a: A, v: V): B0 = a + field[K](v)
}
}
implicitly[Projection.Aux[HNil, Witness.`'thirdField`.T, Boolean, Record.`'thirdField -> Boolean`.T]]
val thirdFieldWitness = Witness('thirdField)
implicitly[Projection.Aux[HNil, thirdFieldWitness.T, Boolean, Record.`'thirdField -> Boolean`.T]]