Anaphory
Anaphory

Reputation: 6432

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
}

Upvotes: 0

Views: 29

Answers (1)

Mateusz Kubuszok
Mateusz Kubuszok

Reputation: 27595

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]]

Upvotes: 1

Related Questions