【问题标题】:Automatic type class derivation for case classes with Scala Enumeration fields具有 Scala 枚举字段的案例类的自动类型类派生
【发布时间】:2017-04-22 22:39:27
【问题描述】:

我已经编写了自动类型类派生,以便为案例类自动生成 elasticsearch Json 映射。 为此,我在无形中使用 TypeClass 类型类。 我遇到的问题是,我们使用的案例类中的许多字段都是 Scala 枚举。 例如

  object ConnectionState extends Enumeration {
    type ConnectionState = Value
    val ordering, requested, pending, available, down, deleting, deleted, rejected = Value
  }

或者

object ProductCodeType extends Enumeration {
    type ProductCodeType = Value
    val devpay, marketplace = Value
  }

似乎我必须为定义的每个枚举定义一个特定的隐式实例,以便自动派生将其拾取(例如,ConnectionStateProductCodeType)。 我不能有一个 implicit def 用于枚举,例如

  implicit def enumerationMapping: MappingEncoder[Enumeration] = new MappingEncoder[Enumeration] {
    def toMapping = jSingleObject("type", jString("text"))
  }

这将适用于所有枚举类型。 我尝试使类型类协变,以及一堆其他的东西,但没有任何帮助。 有什么想法吗?

这里是推导代码:

  object Mapping {
    trait MappingEncoder[T] {
      def toMapping: Json
    }
    object MappingEncoder extends LabelledProductTypeClassCompanion[MappingEncoder] {
      implicit val stringMapping: MappingEncoder[String] = new MappingEncoder[String] {
        def toMapping = jSingleObject("type", jString("text"))
      }
      implicit val intMapping: MappingEncoder[Int] = new MappingEncoder[Int] {
        def toMapping = jSingleObject("type", jString("integer"))
      }
      implicit def seqMapping[T: MappingEncoder]: MappingEncoder[Seq[T]] = new MappingEncoder[Seq[T]] {
        def toMapping = implicitly[MappingEncoder[T]].toMapping
      }
      implicit def optionMapping[T: MappingEncoder]: MappingEncoder[Option[T]] = new MappingEncoder[Option[T]] {
        def toMapping = implicitly[MappingEncoder[T]].toMapping
      }
      object typeClass extends LabelledProductTypeClass[MappingEncoder] {
        def emptyProduct = new MappingEncoder[HNil] {
          def toMapping = jEmptyObject
        }

        def product[F, T <: HList](name: String, sh: MappingEncoder[F], st: MappingEncoder[T]) = new MappingEncoder[F :: T] {
          def toMapping = {
            val head = sh.toMapping
            val tail = st.toMapping
            (name := head) ->: tail
          }
        }
        def project[F, G](instance: => MappingEncoder[G], to: F => G, from: G => F) = new MappingEncoder[F] {
          def toMapping = jSingleObject("properties", instance.toMapping)
        }
      }
    }
  }

【问题讨论】:

    标签: scala typeclass shapeless


    【解决方案1】:

    我能够通过向范围添加额外的隐式定义来解决问题:

    implicit def enumerationMapping[T <: Enumeration#Value]: MappingEncoder[T] = new MappingEncoder[T] {
      def toMapping = jSingleObject("type", jString("text"))
    }
    implicit def enumerationSeqMapping[T <: Enumeration#Value]: MappingEncoder[Seq[T]] = new MappingEncoder[Seq[T]] {
      def toMapping = jSingleObject("type", jString("text"))
    }
    

    需要第二个隐式,因为一些案例类具有 Seq[T] 类型的成员,其中 T 是某种枚举类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 2010-11-11
      • 2014-12-17
      • 2011-04-10
      • 2018-11-24
      • 2014-08-03
      • 1970-01-01
      相关资源
      最近更新 更多