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
values
as anIArray[E]
- reflection of
name
(String
) orordinal
(Int
) for any individual case. - safe lookup individual cases by
name
orordinal
, - unsafe (efficient) lookup of individual cases by
name
orordinal
.
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, Blue
In 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 Sunday
here is a demonstration of using the numeric operators, e.g.
scala> -(-Wednesday) == Wednesday
true