I am trying to create a type class that allows to select a field for a given type. This is what I have done so far but the compiler is unable to find the Selector.Aux
case class AddressKey(street: String, city: String)
trait AddressKeySelector[A] {
def addressKey(v: A): AddressKey
def addressKeyColumnName: String
}
object AddressKeySelector {
implicit def typeAddressKeySelector[A, Repr <: HList, K](
implicit gen: Generic.Aux[A, Repr],
reprSelector: Selector.Aux[Repr, K, AddressKey]): AddressKeySelector[A] =
new AddressKeySelector[A] {
override def addressKey(v: A): AddressKey = reprSelector(gen.to(v))
override def addressKeyColumnName: String = ???
}
}
It will be used like this
case class MyType(addressKeyField: AddressKey, otherField: String)
val data = MyType(AddressKey("addr", "city"), "other")
val addrKey = AddressKeySelector[MyType].addressKey(data)
// addrKey: AddressKey = AddressKey(addr,city)
val addrField = AddressKeySelector[MyType].addressKeyColumnName(data)
// addrField: String = addressKeyField
This should just work when there is one and only one field with type AddressKey. Any idea on how to implement it?
ops.hlist.Selectordoesn't have anAux, so I'm assuming you're using that one. Seeing as you want to extract the field name you probably want to useLabelledGenericandops.record.Selectorinstead. But thenSelector.Aux[Repr, K, AddressKey]would still not work becauseSelectorcan only search by "key" (K) and not by "value" (AddressKey) while you are searching for the key by the value.Ideally I think you would implement it like this:
But for some reason that doesn't work.
So I think your best bet is implementing the search by value yourself. It's relatively straightforward. You can take inspiration from the
ops.hlist.Selector. Keeping in mind that every entry in theHlistthat is emitted byLabelledGenericis encoded aslabelled.FieldType[Key,Value]and that you can get the runtime value ofKey(or in other words: the field name) withWitness.Aux[Key].