scalabeginner

Enum Patterns and Exhaustive Matching

Define and use enums in Scala 3: values, parameters, methods, and exhaustive pattern matching.

scala
// Basic enum
enum Season:
  case Spring, Summer, Autumn, Winter

// Enum with parameters
enum Planet(val mass: Double, val radius: Double):
  case Mercury extends Planet(3.303e+23, 2.4397e6)
  case Venus   extends Planet(4.869e+24, 6.0518e6)
  case Earth   extends Planet(5.976e+24, 6.37814e6)
  case Mars    extends Planet(6.421e+23, 3.3972e6)

  // Method on enum
  def surfaceGravity: Double =
    val G = 6.67300e-11
    G * mass / (radius * radius)

  def surfaceWeight(otherMass: Double): Double =
    otherMass * surfaceGravity

// Enum with methods and ADT
enum HttpMethod:
  case GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS

  def isIdempotent: Boolean = this match
    case GET | PUT | DELETE | HEAD | OPTIONS => true
    case POST | PATCH => false

  def isSafe: Boolean = this match
    case GET | HEAD | OPTIONS => true
    case _ => false

// ADT enum with data
enum Shape:
  case Circle(radius: Double)
  case Rectangle(width: Double, height: Double)
  case Triangle(a: Double, b: Double, c: Double)

  def area: Double = this match
    case Circle(r) => Math.PI * r * r
    case Rectangle(w, h) => w * h
    case Triangle(a, b, c) =>
      val s = (a + b + c) / 2
      Math.sqrt(s * (s - a) * (s - b) * (s - c))

  def perimeter: Double = this match
    case Circle(r) => 2 * Math.PI * r
    case Rectangle(w, h) => 2 * (w + h)
    case Triangle(a, b, c) => a + b + c

// Enum with type parameter
enum Result[+T]:
  case Ok(value: T)
  case Err(message: String)

  def map[U](f: T => U): Result[U] = this match
    case Ok(v) => Ok(f(v))
    case Err(m) => Err(m)

  def flatMap[U](f: T => Result[U]): Result[U] = this match
    case Ok(v) => f(v)
    case Err(m) => Err(m)

  def getOrElse[U >: T](default: => U): U = this match
    case Ok(v) => v
    case Err(_) => default

@main def run(): Unit =
  // Season
  import Season.*
  val season = Summer
  val msg = season match
    case Spring => "Flowers bloom"
    case Summer => "Sun shines"
    case Autumn => "Leaves fall"
    case Winter => "Snow falls"
  println(s"$season: $msg")

  // Enum values
  println(s"All seasons: ${Season.values.mkString(", ")}")
  println(s"From string: ${Season.valueOf("Winter")}")
  println(s"Ordinal: ${Winter.ordinal}")

  // Planet
  val earth = Planet.Earth
  println(f"\nEarth gravity: ${earth.surfaceGravity}%.2f m/s²")
  println(f"80kg on Earth: ${earth.surfaceWeight(80)}%.2f N")
  println(f"80kg on Mars: ${Planet.Mars.surfaceWeight(80)}%.2f N")

  // HTTP
  println(s"\nGET idempotent: ${HttpMethod.GET.isIdempotent}")
  println(s"POST safe: ${HttpMethod.POST.isSafe}")

  // Shape
  val shapes = List(
    Shape.Circle(5),
    Shape.Rectangle(4, 6),
    Shape.Triangle(3, 4, 5)
  )
  shapes.foreach { s =>
    println(f"  ${s}: area=${s.area}%.2f, perimeter=${s.perimeter}%.2f")
  }

  // Result
  val ok: Result[Int] = Result.Ok(42)
  val err: Result[Int] = Result.Err("not found")
  println(s"\nOk mapped: ${ok.map(_ * 2)}")
  println(s"Err mapped: ${err.map(_ * 2)}")
  println(s"Err default: ${err.getOrElse(0)}")

Use Cases

  • Defining finite sets of values
  • Algebraic data types
  • Exhaustive state handling

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.