2

我正在尝试创建一个允许为给定类型选择字段的类型类。这是我到目前为止所做的,但编译器无法找到 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 类型的字段时,这应该才有效。关于如何实施它的任何想法?

4

1 回答 1

2

ops.hlist.Selector没有Aux,所以我假设你正在使用那个。看到你想要提取你可能想要使用的字段名称LabelledGeneric,而ops.record.Selector不是。但是Selector.Aux[Repr, K, AddressKey]那样仍然不起作用,因为在您按值搜索键时,Selector只能按“键”(K)而不是“值”(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
    }
}

但由于某种原因,这不起作用。

所以我认为你最好的选择是自己实施价值搜索。它相对简单。您可以从ops.hlist.Selector. 请记住,Hlist由 发出的每个条目都LabelledGeneric被编码为labelled.FieldType[Key,Value],并且您可以Key使用Witness.Aux[Key].

于 2017-06-10T20:02:29.813 回答