Enums, Part 2

Scala 3 Enums (Enumerations): Advanced Features

Advanced features of Scala 3 enums:

  • Enums can be parameterized
  • Enums can have members

Enums can be parameterized

Example of HTTP response codes:

// define (a) the HttpResponse type and (b) its values
// (or instances)
enum HttpResponse(val code: Int):
    case Ok extends HttpResponse(200)
    case MovedPermanently extends HttpResponse(301)
    case InternalServerError extends HttpResponse(500)

// import the values
import HttpResponse.*

// use the values
Ok.code                        // 200
MovedPermanently.code          // 301
InternalServerError.code       // 500

Example of a deck of cards:

// enums can be parametrized
enum Suit(val symbol: String):
    case Hearts extends Suit("♥")
    case Diamonds extends Suit("♦")
    case Clubs extends Suit("♣")
    case Spades extends Suit("♠")

enum Rank(val value: Int):
    case Two extends Rank(2)
    case Three extends Rank(3)
    case Four extends Rank(4)
    case Five extends Rank(5)
    case Six extends Rank(6)
    case Seven extends Rank(7)
    case Eight extends Rank(8)
    case Nine extends Rank(9)
    case Ten extends Rank(10)
    case Jack extends Rank(11)
    case Queen extends Rank(12)
    case King extends Rank(13)
    case Ace extends Rank(14)

case class Card(rank: Rank, suit: Suit):
    override def toString =
        s"$rank of $suit"

val deckOfCards: Seq[Card] = for
    rank <- Rank.values.toSeq
    suit <- Suit.values.toSeq
yield
    Card(rank, suit)

import scala.util.Random
val d2 = Random.shuffle(deckOfCards)

Examples of parameters and members (fields and methods)

Here’s a partial example of using enum parameters and members (which are fields and methods). This comes from this LAMP/EPFL Scala page:

enum Planet(mass: Double, radius: Double):
    // fields
    private final val G = 6.67300E-11
    // methods:
    def surfaceGravity = G * mass / (radius * radius)
    def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity
    // cases:
    case Mercury extends Planet(3.303e+23, 2.4397e6)
    case Earth extends Planet(5.976e+24, 6.37814e6)
    // ...
    
    // note: methods are not unique to instances.
    // if you want a “carbonPercent” method for just Earth,
    // you can’t do that

When to use an enum?

Use a Scala 3 enum when:

  • You want to model a small (or relatively small), finite set of values
  • When the values (instances) won’t ever need unique members (fields and methods)
    • i.e., you would like to have a atmosphericCarbon method for Earth, but you can’t create a unique method like that
  • In FP we use enums to define ADTs (i.e., simple sum types, such as those shown in this page)
    • Examples: Directions, Toppings, CrustSize, CrustType, Suit, Rank

For more information on ADTs, see: