Proposal for Enumerations in Scala

What bothers me quite a bit with this proposal is the conflation of two features into one construct:

  1. Enumerated types.
  2. Concise syntax for sealed types hierarchies – for instance, ADTs.

This is not the first case in the language where this happens – see implicits for example – and I believe it’s a source for confusion and an obstruction of designing syntax that is better suited / tailored to the specific needs of each feature.

Enumerated types are constant and unique values that have unique identifiers; sealed types do not exhibit any of these characteristics.

For example, what will these return?

Option.valueOf("Some")
Option.values()

They surely cannot return an instantiated object for Some.

I suspect that the confusion between the two stems from the pattern in which enums are encoded nowadays in Scala 2 (sealed trait + objects). However, it’s possible to encode them differently using opaques (which are in fact possible in Scala 2):

object Colors {
  opaque type Color = Int

  private[this] case class Data(name: String, rgb: Int)

  private[this] val colorToData = mutable.Map.empty[Color, Data]

  private[this] def apply(ordinal: Int, name: String, rgb: Int): Color = {
    colorToData.put(ordinal, Data(name, rgb))
    ordinal
  }

  object Color {
    def valueOf(name: String): Color = colorToData.find(_._2.name == name).get._1
    def values(): Array[Color] = colorToData.keys.toArray

    val Red = Color(0, "Red", 0xFF0000)
    val Green = Color(1, "Green", 0x00FF00)
    val Blue = Color(2, "Blue", 0x0000FF)
  } 
 
  extension ops on (color: Color) {
    def ordinal: Int = color
    def name: String = colorToData(color).name
    def rgb: Int = colorToData(color).rgb
  }
}

This is not very useful as it requires a lot of boilerplate, but this demonstrates how enums are not about sealed types, but rather about a constant set of identifiable values.

3 Likes