We want to create an encoder for arbitrary Enumerations with frameless which
is basically creating a bidirectional mapping from an arbitrary Enumeration to Byte. Currently our less than optimal solution is to give evidence on all of our Enumeration instances so the deserializer can pick it up and call apply on that instance, a method that creates an Enumeration from a Byte. We want to find a way without defining these implicit values, and rather have them automatically picked up from the E type. As far as we know object types are in one-to-one correspondence to a single instance, so we hope there's a mechanism to do this.
For example, the following works
import frameless._
object Color extends Enumeration {
type Color = Value
val Red, Green, Blue = Value
}
object State extends Enumeration {
type State = Value
val Running, Stopped, Finished = Value
}
implicit val colorEvidence = Color // we want to spare these lines
implicit val stateEvidence = State // we want to spare these lines
implicit def enumToByteInjection[E <: Enumeration](implicit e: E):
Injection[E#Value, Byte] = Injection(_.id.toByte, e.apply(_))
Solution 1 (reflection)
This here compiles and runs when compiled with
scalac 2.12.4:It of course crashes because of the missing implementation at
???, but this comes after the implicit companion object is summoned into existence.Gotchas:
classOf[Unit].classLoaderleads toNoSuchClassExceptions.TypeTags for the enums (shouldn't be a problem when used with concrete enums on top-level, but could become a problem if the method is supposed to be buried deep in a library but still have "access to the surface": then you would have to pullTypeTags through every method to the surface).Solution 2 (implicit objects)
If you have all enums under your control, then you could simply declare the enumeration objects themselves
implicit. The following compiles just nicely, all implicits are inserted as expected: