Scala 3 — Book

# 代数数据类型

Language

## 枚举

enumeration 用于定义由一组命名值组成的类型：

enum Color:
case Red, Green, Blue

enum Color:
case Red   extends Color
case Green extends Color
case Blue  extends Color

#### 参数

enum Color(val rgb: Int):
case Red   extends Color(0xFF0000)
case Green extends Color(0x00FF00)
case Blue  extends Color(0x0000FF)

println(Color.Green.rgb) // prints 65280

#### 自定义

private final val G = 6.67300E-11
def surfaceWeight(otherMass: Double) =  otherMass * surfaceGravity

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)
// 5 or 6 more planets ...

object Planet:
def main(args: Array[String]) =
val earthWeight = args(0).toDouble
val mass = earthWeight / Earth.surfaceGravity
for (p <- values)
println(s"Your weight on \$p is \${p.surfaceWeight(mass)}")

enum Option[+T]:
case Some(x: T)
case None

enum Option[+T]:
case Some(x: T) extends Option[T]
case None       extends Option[Nothing]

scala> Option.Some("hello")
val res1: t2.Option[String] = Some(hello)

scala> Option.None
val res2: t2.Option[Nothing] = None

enum Option[+T]:
case Some(x: T)
case None

def isDefined: Boolean = this match
case None => false
case Some(_) => true

object Option:
def apply[T >: Null](x: T): Option[T] =
if (x == null) None else Some(x)

enum Color(val rgb: Int):
case Red   extends Color(0xFF0000)
case Green extends Color(0x00FF00)
case Blue  extends Color(0x0000FF)
case Mix(mix: Int) extends Color(mix)

#### 递归枚举

enum Nat:
case Zero
case Succ(n: Nat)

enum List[+A]:
case Nil

enum Box[T](contents: T):
case IntBox(n: Int) extends Box[Int](n)
case BoolBox(b: Boolean) extends Box[Boolean](b)

def extract[T](b: Box[T]): T = b match
case IntBox(n)  => n + 1
case BoolBox(b) => !b

## 去除语法糖的枚举

sealed abstract class Color(val rgb: Int) extends scala.reflect.Enum
object Color:
case object Red extends Color(0xFF0000) { def ordinal = 0 }
case object Green extends Color(0x00FF00) { def ordinal = 1 }
case object Blue extends Color(0x0000FF) { def ordinal = 2 }
case class Mix(mix: Int) extends Color(mix) { def ordinal = 3 }

def fromOrdinal(ordinal: Int): Color = ordinal match
case 0 => Red
case 1 => Green
case 2 => Blue
case _ => throw new NoSuchElementException(ordinal.toString)