Getting all values of a generic enumeration

In Scala 3, is there a way to get all the values of an enum generically?

def allEnumValues[E]: Array[E] = ???

Perhaps by somehow getting a hold of the companion object?

def allEnumValues[E <: EnumBaseType : EnumObject]: Array[E] =
  summon[EnumObject[E]].values

Perhaps mirrors are what you’re looking for?

Here’s an implementation that works for enum values without parameters, and isn’t type safe:

object EnumX:
    enum Color:
        case Red, Green, Blue

    inline def allEnumValues[E](using m: Mirror.SumOf[E]): List[?] =
        tToList[m.MirroredElemTypes]

    inline def productValue[E] = summonFrom {
        case m: Mirror.ProductOf[E] => m.fromProduct(EmptyTuple) // <- this assumes that the enum case constructor takes no parameters  
    }

    inline def tToList[T <: Tuple]: List[?] =
        inline erasedValue[T] match
            case _: EmptyTuple => Nil
            case _: (h *: t) => productValue[h] :: tToList[t]

    val c: Color = allEnumValues[Color](0).asInstanceOf[Color] // <- need this type cast to compile

I’d love to see how this can be improved by someone who didn’t just read about mirrors and compile time ops

1 Like

I made a library enum-extensions to do this

e.g.

import enumextensions.EnumMirror

enum Color derives EnumMirror:
  case Red, Green, Blue

def sortedCases[E: EnumMirror]: IArray[E] =
  EnumMirror[E].values // cached IArray

feedback is very welcome

2 Likes

Super cool library! I’m learning a lot about macros reading through the code. Do you know how it works for enum cases that take parameters?
I’m still trying to figure out a more type-safe compile time ops/macro-less way to get there. I think I’m getting closer, but not sure why I’m getting the compilation error here:

it only supports enumerated (singleton cases only) or else there should be compile time error

1 Like