title: Automatic type class derivation for case classes with Scala Enumeration fields
body: <p>I have written automatic type class derivation in order to automatically generate elasticsearch Json mapping for case classes.
  For that I am using the TypeClass type class in shapeless.
  The problem I have is that many fields in the case classes we use are Scala enumerations.
  For example </p>
  
  <pre><code>  object ConnectionState extends Enumeration {
      type ConnectionState = Value
      val ordering, requested, pending, available, down, deleting, deleted, rejected = Value
    }
  </code></pre>
  
  <p>Or </p>
  
  <pre><code>object ProductCodeType extends Enumeration {
      type ProductCodeType = Value
      val devpay, marketplace = Value
    }
  </code></pre>
  
  <p>It seems I have to define a specific implicit instance for every Enumeration that is defined in order that the automatic derivation will pick it up (e.g. for both <code>ConnectionState</code> and <code>ProductCodeType</code>).
  I cannot have one <code>implicit def</code> for Enumeration such as </p>
  
  <pre><code>  implicit def enumerationMapping: MappingEncoder[Enumeration] = new MappingEncoder[Enumeration] {
      def toMapping = jSingleObject("type", jString("text"))
    }
  </code></pre>
  
  <p>that will work for all enumeration types.
  I tried making the type class covariant, and a bunch of other things but nothing helped.
  Any ideas?</p>
  
  <p>Here is the derivation code:</p>
  
  <pre><code>  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 &lt;: 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) -&gt;: tail
            }
          }
          def project[F, G](instance: =&gt; MappingEncoder[G], to: F =&gt; G, from: G =&gt; F) = new MappingEncoder[F] {
            def toMapping = jSingleObject("properties", instance.toMapping)
          }
        }
      }
    }
  </code></pre>