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
``````

#### 自定义

``````enum Planet(mass: Double, radius: Double):

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` 概念足够通用，既支持_代数数据类型_（ADT）和它的通用版本（GADT）。 本示例展示了如何将 `Option` 类型表示为 ADT：

``````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)
``````