Select 字段(按类型)
Select field by type
我正在尝试创建一个类型 class,允许 select 给定类型的字段。这是我到目前为止所做的,但编译器无法找到 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 = ???
}
}
会这样使用
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
当只有一个字段的类型为 AddressKey 时,这应该才有效。关于如何实施它的任何想法?
ops.hlist.Selector
没有 Aux
,所以我假设您正在使用那个。鉴于您想要提取您可能想要使用 LabelledGeneric
和 ops.record.Selector
的字段名称。但是 Selector.Aux[Repr, K, AddressKey]
仍然不起作用,因为 Selector
只能按 "key" (K
) 搜索,而不能按 "value" (AddressKey
) 搜索,而你正在按值搜索键。
理想情况下,我认为你会像这样实现它:
import shapeless._, ops.record._
trait AddressKeySelector[A] {
def addressKey(v: A): AddressKey
def addressKeyColumnName: String
}
object AddressKeySelector {
def apply[A](implicit sel: AddressKeySelector[A]): sel.type = sel
implicit def typeAddressKeySelector[A, Repr <: HList, K <: Symbol, Swapped <: HList](
implicit
gen: LabelledGeneric.Aux[A, Repr],
swap: SwapRecord.Aux[Repr, Swapped],
swappedSelector: Selector.Aux[Swapped, AddressKey, K],
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 = swappedSelector(swap()).name
}
}
但是对于 some reason 这不起作用。
所以我认为您最好的选择是自己实施按值搜索。它相对简单。您可以从 ops.hlist.Selector
中获得灵感。请记住,LabelledGeneric
发出的 Hlist
中的每个条目都被编码为 labelled.FieldType[Key,Value]
并且您可以获得 Key
的运行时值(或者换句话说:字段名称)与 Witness.Aux[Key]
.
我正在尝试创建一个类型 class,允许 select 给定类型的字段。这是我到目前为止所做的,但编译器无法找到 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 = ???
}
}
会这样使用
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
当只有一个字段的类型为 AddressKey 时,这应该才有效。关于如何实施它的任何想法?
ops.hlist.Selector
没有 Aux
,所以我假设您正在使用那个。鉴于您想要提取您可能想要使用 LabelledGeneric
和 ops.record.Selector
的字段名称。但是 Selector.Aux[Repr, K, AddressKey]
仍然不起作用,因为 Selector
只能按 "key" (K
) 搜索,而不能按 "value" (AddressKey
) 搜索,而你正在按值搜索键。
理想情况下,我认为你会像这样实现它:
import shapeless._, ops.record._
trait AddressKeySelector[A] {
def addressKey(v: A): AddressKey
def addressKeyColumnName: String
}
object AddressKeySelector {
def apply[A](implicit sel: AddressKeySelector[A]): sel.type = sel
implicit def typeAddressKeySelector[A, Repr <: HList, K <: Symbol, Swapped <: HList](
implicit
gen: LabelledGeneric.Aux[A, Repr],
swap: SwapRecord.Aux[Repr, Swapped],
swappedSelector: Selector.Aux[Swapped, AddressKey, K],
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 = swappedSelector(swap()).name
}
}
但是对于 some reason 这不起作用。
所以我认为您最好的选择是自己实施按值搜索。它相对简单。您可以从 ops.hlist.Selector
中获得灵感。请记住,LabelledGeneric
发出的 Hlist
中的每个条目都被编码为 labelled.FieldType[Key,Value]
并且您可以获得 Key
的运行时值(或者换句话说:字段名称)与 Witness.Aux[Key]
.