scalascala-3

How to use generic enum's values in a function


A am picking up Scala 3 again after a very long time away from Scala. I deal with a lot of enum conversions, so I want to write a helper function that gives me enum values by name in a map. How do I write a function like this?

def enumMap[E: enum]: Map[String, E] = {
  E.values.map(
    value => (value.toString, value)
  ).toMap
}

Solution

  • Out of the box, you cannot, as there is no type bound nor build-in type class which provides such behavior generically. You'd have to define a type class and implement it, or use a library which does like enumz:

    enum Foo:
      case Bar
      case Baz
    
    import io.scalaland.enumz.Enum
    
    def enumMap[E: Enum]: Map[String, E] = {
      Enum[E].values.map(
        value => (value.toString, value)
      ).toMap
    }
    
    enumMap[Foo]
    

    If you wanted to do it yourself, you could use Mirrors:

    import scala.deriving.Mirror
    import scala.compiletime.*
    import scala.reflect.ClassTag
    
    class Enum[E](val values: IArray[E])
    
    object Enum:
    
      inline given scalaEnum[E: ClassTag](using m: Mirror.SumOf[E]): Enum[E] =
        Enum(
          IArray.from(
            summonAll[Tuple.Map[m.MirroredElemTypes, ValueOf]].toList
              .asInstanceOf[List[ValueOf[E]]]
              .map(_.value)
          )
        )
    
    enum Foo:
      case Bar
      case Baz
    
    summon[Enum[Foo]]