按类型

时间:2017-06-09 20:24:24

标签: scala shapeless scala-implicits

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

1 个答案:

答案 0 :(得分:2)

ops.hlist.Selector没有Aux,因此我假设您正在使用该LabelledGeneric。如果您要提取字段名称,则可能需要使用ops.record.SelectorSelector.Aux[Repr, K, AddressKey]。但是Selector仍然无效,因为K只能按&#34;键&#34; (AddressKey)而不是&#34;价值&#34; (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 } } ),当您按值搜索密钥时。

理想情况下,我认为你会像这样实现它:

Hlist

some reason无效。

所以我认为你最好的选择是自己实现价值搜索。它相对简单。你可以从ops.hlist.Selector中获取灵感。请记住,LabelledGeneric发出的labelled.FieldType[Key,Value]中的每个条目都被编码为Key,并且您可以获得Witness.Aux[Key]的运行时值(换句话说:字段名称)public async Task Send(string userId, string devicePushToken, string content) { string json = JsonConvert.SerializeObject(new { tokens = new[] {devicePushToken}, profile = "yourprofile", notification = new { message = content } }); var restClient = new RestClient("https://api.ionic.io/"); var restRequest = new RestRequest("push/notifications", Method.POST); restRequest.AddHeader("Accept", "application/json"); restRequest.AddParameter("application/json", json, ParameterType.RequestBody); restRequest.AddParameter("Authorization", "Bearer APIKEY", ParameterType.HttpHeader); await restClient.ExecuteTaskAsync(restRequest); }