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].classLoader
leads toNoSuchClassException
s.TypeTag
s 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 pullTypeTag
s 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: