0Pricing
Scala for Backend Engineering & Functional Programming · 课时

常见类型类

Show、Ordering、Numeric

常见类型类 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Scala for Backend Engineering & Functional Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

标准类型类

Scala 标准库提供了多个您每天都会使用、有时甚至没有意识到的类型类:

  • Ordering[A] — 定义如何比较值。
  • Numeric[A] — 定义对数字执行的算术运算。
  • Show 风格的渲染(自定义实现,或 Cats 的 Show)。

Ordering 赋能 sorted

List.sorted 需要一个隐式的 Ordering[A]。标准库为数字、字符串等类型提供了实例。

@main def run(): Unit = {
  println(List(3, 1, 2).sorted)
  println(List("pear", "apple", "fig").sorted)
}

自定义 Ordering

传入一个显式的 Ordering,即可采用不同的排序方式,例如按降序排序或根据派生键排序。

@main def run(): Unit = {
  val nums = List(3, 1, 2)
  println(nums.sorted(Ordering.Int.reverse))
  val words = List("bbb", "a", "cc")
  println(words.sortBy(_.length))
}

样例类的 Ordering

为您自己的类型提供一个 Ordering 实例,这样就可以对该类型的集合进行排序。Ordering.by 可以根据某个键派生出排序规则。

case class Person(name: String, age: Int)

object Main {
  implicit val byAge: Ordering[Person] = Ordering.by(_.age)

  def main(args: Array[String]): Unit = {
    val people = List(Person("A", 30), Person("B", 20))
    println(people.sorted)
  }
}

Numeric 抽象出算术运算

Numeric[A] 让您可以编写适用于任意数字类型的函数。对列表使用 sum 时就依赖于它。

@main def run(): Unit = {
  println(List(1, 2, 3).sum)
  println(List(1.5, 2.5).sum)
}

编写泛型数值代码

借助上下文界定 [A: Numeric],您可以用泛型方式对任意数字类型执行加法或乘法。请通过 Numeric[A] 使用实例提供的运算。

object Main {
  def addAll[A: Numeric](xs: List[A]): A = {
    val num = implicitly[Numeric[A]]
    xs.foldLeft(num.zero)(num.plus)
  }

  def main(args: Array[String]): Unit = {
    println(addAll(List(1, 2, 3)))
    println(addAll(List(1.0, 2.0, 3.5)))
  }
}

数值运算符

导入实例的 Implicits 后,泛型数字类型就可以使用常见运算符(+、*),让代码读起来更加自然。

object Main {
  def square[A](a: A)(implicit num: Numeric[A]): A = {
    import num._
    a * a
  }

  def main(args: Array[String]): Unit = {
    println(square(5))
    println(square(2.5))
  }
}

Show 类型类

Show 会以类型安全的方式将值渲染为文本(不同于对所有对象都存在的 toString)。Cats 提供了它;这里展示一个最小实现。

trait Show[A] { def show(a: A): String }

object Show {
  implicit val intShow: Show[Int] = n => s"Int($n)"
  def apply[A](implicit s: Show[A]): Show[A] = s
}

object Main {
  def main(args: Array[String]): Unit = {
    println(Show[Int].show(42))
  }
}

Ordering 与 max/min

集合中的 max、min 和 maxBy 等方法,底层都使用了 Ordering。

@main def run(): Unit = {
  val xs = List(4, 9, 1, 7)
  println(xs.max)
  println(xs.min)
  println(List("a", "abc", "ab").maxBy(_.length))
}

组合 Ordering

您可以对元组使用 Ordering.by 构建组合排序规则,先按一个字段排序,再按另一个字段排序。

case class Rec(group: String, score: Int)

object Main {
  implicit val ord: Ordering[Rec] = Ordering.by(r => (r.group, -r.score))

  def main(args: Array[String]): Unit = {
    val data = List(Rec("b", 5), Rec("a", 1), Rec("a", 9))
    data.sorted.foreach(println)
  }
}

为什么这里使用类型类

由于比较和算术运算都是类型类,因此只需提供实例,同一个 sorted 或 sum 就可以用于内置类型和您自己的类型。这就是标准库对特设多态的使用。

快速检查

测试您对标准类型类的掌握程度。

回顾

您已经了解了常见的标准类型类:

  • Ordering[A] 驱动 sorted、max 和 min;可以使用 Ordering.by 构建。
  • Numeric[A] 支持泛型算术运算,并为 sum 提供支持。
  • Show 风格的类型类可以以类型安全的方式渲染值。

常见问题解答

「常见类型类」课时是免费的吗?

是的 — 「常见类型类」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Scala for Backend Engineering & Functional Programming 课程的其余内容,请升级到 CoddyKit PRO。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

「常见类型类」这节课中我会学到什么?

Show、Ordering、Numeric 你通过在浏览器中直接运行的动手代码来练习 Scala for Backend Engineering & Functional Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Scala for Backend Engineering & Functional Programming 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Scala for Backend Engineering & Functional Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「常见类型类」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Scala for Backend Engineering & Functional Programming 课中编写并运行代码吗?

能。每节 Scala for Backend Engineering & Functional Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 类型类模式
  2. 定义实例
  3. 常见类型类
  4. 类型类派生
← 返回 Scala for Backend Engineering & Functional Programming