Scala3中的代数数据类型(ADTs)深度解析
痛点:类型安全与模式匹配的完美结合
你是否曾在开发过程中遇到过这样的困境:需要处理多种可能的数据结构,但又担心类型安全问题?或者希望在模式匹配时获得编译器的智能类型推断?Scala3的代数数据类型(Algebraic Data Types,ADTs)正是解决这些痛点的利器。
读完本文,你将掌握:
- ADTs的核心概念与数学基础
- Scala3中enum语法的革命性改进
- GADTs(广义代数数据类型)的高级用法
- 模式匹配与类型推断的完美结合
- 实际项目中的最佳实践案例
代数数据类型基础
什么是代数数据类型?
代数数据类型是函数式编程中的核心概念,通过两种基本操作构建复杂类型:
- 积类型(Product Types):类似元组或case class,表示"且"的关系
- 和类型(Sum Types):类似枚举或sealed trait,表示"或"的关系
// 积类型示例:Case Class
case class Person(name: String, age: Int)
// 和类型示例:Sealed Trait + Case Classes
sealed trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(width: Double, height: Double) extends Shape
Scala3的enum语法糖
Scala3引入了全新的enum语法,极大简化了ADTs的定义:
// 传统Scala2方式
sealed trait Color
case object Red extends Color
case object Green extends Color
case object Blue extends Color
// Scala3 enum方式
enum Color:
case Red, Green, Blue
深入enum语法
基本枚举定义
// 简单枚举
enum DayOfWeek:
case Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
// 带参数的枚举
enum Color(val rgb: Int):
case Red extends Color(0xFF0000)
case Green extends Color(0x00FF00)
case Blue extends Color(0x0000FF)
// 方法定义
enum Planet(mass: Double, radius: Double):
case Mercury extends Planet(3.303e+23, 2.4397e6)
case Venus extends Planet(4.869e+24, 6.0518e6)
def surfaceGravity: Double =
Planet.G * mass / (radius * radius)
def surfaceWeight(otherMass: Double): Double =
otherMass * surfaceGravity
object Planet:
val G: Double = 6.67300E-11
代数运算视角
从代数角度看,ADTs支持丰富的类型运算:
广义代数数据类型(GADTs)
GADTs核心概念
GADTs允许我们在类型参数中编码更多信息,实现更精确的类型约束:
// 基本GADT示例
enum Expr[T]:
case IntLit(value: Int) extends Expr[Int]
case StrLit(value: String) extends Expr[String]
case BoolLit(value: Boolean) extends Expr[Boolean]
case Add(left: Expr[Int], right: Expr[Int]) extends Expr[Int]
case Concat(left: Expr[String], right: Expr[String]) extends Expr[String]
GADTs的类型安全魔法
def eval[T](expr: Expr[T]): T = expr match
case Expr.IntLit(i) => i
case Expr.StrLit(s) => s
case Expr.BoolLit(b) => b
case Expr.Add(l, r) => eval(l) + eval(r)
case Expr.Concat(l, r) => eval(l) + eval(r)
// 编译器知道每个分支返回的确切类型
val result1: Int = eval(Expr.Add(Expr.IntLit(1), Expr.IntLit(2)))
val result2: String = eval(Expr.Concat(Expr.StrLit("Hello"), Expr.StrLit("World")))
复杂GADTs模式
// 类型级自然数
enum Nat:
case Zero
case Succ(prev: Nat)
// 长度索引列表
enum Vec[N <: Nat, +A]:
case Nil extends Vec[Nat.Zero, Nothing]
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



