scala - 获取字段键作为副产品

标签 scala shapeless

import shapeless._
import syntax.singleton._

val book = ("author" ->> "Benjamin Pierce") ::
  ("title"  ->> "Types and Programming Languages") ::
  ("id"     ->>  "foo") ::
  ("price"  ->>  "bar") ::
  HNil

我想找到映射到 "foo" 的字段键(在本例中为 "id")并检索它,输入为 4 单例的联积字符串。

我该怎么做?

最佳答案

我建议使用自定义类型类以不同方式(并且更通用)来执行此操作:

import shapeless._
import shapeless.labelled.FieldType

trait RecSearch[R <: HList, A] {
  type Keys <: Coproduct

  def find(r: R, a: A): Option[Keys]
}

object RecSearch extends LowPriorityRecSearchInstances {
  implicit def hnilRecSearch[A]: Aux[HNil, A, CNil] =
    new RecSearch[HNil, A] {
      type Keys = CNil

      def find(r: HNil, v: A): Option[CNil] = None
    }

  implicit def cconsRecSearch1[K, V, T <: HList](implicit
    trs: RecSearch[T, V],
    wit: Witness.Aux[K]
  ): Aux[FieldType[K, V] :: T, V, K :+: trs.Keys] =
    new RecSearch[FieldType[K, V] :: T, V] {
      type Keys = K :+: trs.Keys

      def find(r: FieldType[K, V] :: T, a: V): Option[K :+: trs.Keys] =
        if (r.head == a)
          Some(Coproduct[K :+: trs.Keys](wit.value))
        else trs.find(r.tail, a).map(_.extendLeft[K])
    }
}

trait LowPriorityRecSearchInstances {
  type Aux[R <: HList, A, K <: Coproduct] = RecSearch[R, A] { type Keys = K }

  implicit def cconsRecSearch0[A, K, V, T <: HList](implicit
    trs: RecSearch[T, A]
  ): Aux[FieldType[K, V] :: T, A, K :+: trs.Keys] =
    new RecSearch[FieldType[K, V] :: T, A] {
      type Keys = K :+: trs.Keys

      def find(r: FieldType[K, V] :: T, a: A): Option[K :+: trs.Keys] =
        trs.find(r.tail, a).map(_.extendLeft[K])
    }
}

然后:

def search[R <: HList, A](r: R)(a: A)(implicit rs: RecSearch[R, A]): Option[rs.Keys] =
  rs.find(r, a)

最后:

import syntax.singleton._

val book = ("author" ->> "Benjamin Pierce") ::
  ("title"  ->> "Types and Programming Languages") ::
  ("id"     ->>  "foo") ::
  ("price"  ->>  "bar") ::
  HNil

search(book)("foo")

这将向您显示(非常详细的)副产品类型和正确的值:

Some(Inr(Inr(Inl(id))))

你的版本不适合我编译,所以我不能真正比较两者,但 95% 的时间我开始使用 Poly 我最终切换到一个类型类一些点。

关于scala - 获取字段键作为副产品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36943693/

相关文章:

scala - 如何通过隐式分解类型构造函数?

无处不在的无形和异步计算

scala - Spray-json序列化继承案例类

scala - 我将如何在 Scala 中生成一个 immutable.Map?

scala - 在 Scala 元组上使用函数组合器?

scala - 固定大小和元素边界的 Nat 列表

javascript - Scala 到 JavaScript 的编译有效吗?

scala 使用的是随二进制分发版一起提供的 akka 而不是 sbt 的

scala - 使用列名数组聚合 Spark 数据框,保留名称

scala - 如何在 Scala 中实现异构容器