The Enum Extensions library provides type classes to work generically with enumerations in Scala 3
Type classes are provided in the enumextensions package.
EnumMirror[E] is a type class that provides reflection over an enumeration type E. It provides several capabilities:
- cached
valuesas anIArray[E] - reflection of
name(String) orordinal(Int) for any individual case. - safe lookup individual cases by
nameorordinal, - unsafe (efficient) lookup of individual cases by
nameorordinal.
See the above use cases in action below:
import enumextensions.EnumMirror
def enumName[E: EnumMirror]: String =
EnumMirror[E].mirroredName // e.g. example.Color
def sortedCases[E: EnumMirror]: IArray[E] =
EnumMirror[E].values // cached IArray
def nameOrdinalPairs[E: EnumMirror]: Map[String, Int] =
Map.from( // ┌ NAME ┌ ORDINAL
for e <- sortedCases[E] yield e.name -> e.ordinal
)
// Lookups returning `Option[E]`
def safeLookup[E: EnumMirror](name: String): Option[E] =
EnumMirror[E].valueOf(name)
def safeLookup[E: EnumMirror](ordinal: Int): Option[E] =
EnumMirror[E].fromOrdinal(ordinal)
// assert that name/ordinal exists for convenience
def unsafeLookup[E: EnumMirror](name: String): E =
EnumMirror[E].valueOfUnsafe(name)
def unsafeLookup[E: EnumMirror](ordinal: Int): E =
EnumMirror[E].fromOrdinalUnsafe(ordinal)given instances of EnumMirror are not provided automatically, you must explicitly opt in as follows:
enum Color derives EnumMirror:
case Red, Green, BlueIn the enumextensions.numeric package we provide NumericOps, which extends types with a given EnumMirror[E] into a given scala.math.Integral[E], as well as providing standard numeric operations over the enum, it is simple to create sub-ranges of values.
Let's define a WeekDays enumeration, opting into numeric derivation by derives NumericOps, and declare ranges for both the daysOfWeek and weekend:
import enumextensions.EnumMirror
import enumextensions.numeric.NumericOps
enum WeekDays derives EnumMirror, NumericOps:
case Monday, Tuesday, Wednesday, Thursday, Friday
case Saturday, Sunday
object WeekDays:
val daysOfWeek = Monday to Friday
val weekend = Saturday to Sundayhere is a demonstration of using the numeric operators, e.g.
scala> -(-Wednesday) == Wednesday
true