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

组合 IO

排列效果执行顺序

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

使用 flatMap 按顺序执行

由于 IO 是一个 monad,您可以使用 flatMap 组合效应。每一步都会按顺序运行,后续步骤可以使用前一步的结果。

import cats.effect.IO

val program: IO[Unit] =
  IO("Alice").flatMap(name => IO.println(s"Hello, $name"))

for 推导式

for 推导式会展开为 flatMap/map,读起来像命令式脚本,同时保持纯粹性。

import cats.effect.IO

val prog: IO[Unit] = for {
  _    <- IO.println("What is your name?")
  name <- IO("Bob")
  _    <- IO.println(s"Hi $name")
} yield ()

保持执行顺序

for 推导式中的效应会在程序执行时从上到下运行。代码结构与执行顺序相互对应。

组合相互独立的效应

当两个效应互不依赖时,请使用 mapN 或 (a, b).tupled 将它们组合起来。默认情况下,它们仍会按顺序运行,但代码表达了它们彼此独立。

import cats.effect.IO
import cats.syntax.apply._

val combined: IO[Int] = (IO(2), IO(3)).mapN(_ + _)

并行运行效应

使用 parMapN(来自 cats.syntax.parallel)在不同纤程上并发运行相互独立的效应,并组合它们的结果。

import cats.effect.IO
import cats.syntax.parallel._

val par: IO[Int] = (IO(2), IO(3)).parMapN(_ + _)

丢弃结果

使用 *> 运行一个效应并保留第二个结果,或使用 <* 保留第一个结果。void 会完全丢弃结果,得到 IO[Unit]。

import cats.effect.IO

val r1: IO[Int]  = IO.println("log") *> IO(42)
val r2: IO[Unit] = IO(99).void

重复执行效应

replicateA(n) 会运行一个效应 n 次,并将结果收集到列表中。foreverM 会无限重复。

import cats.effect.IO

val three: IO[List[Unit]] = IO.println("tick").replicateA(3)

遍历列表

使用 traverse 将 List[A] 转换为作用于 List[B] 的效应。每个元素都会产生一个 IO,然后收集所有结果。

import cats.effect.IO
import cats.syntax.traverse._

val names = List("a", "b", "c")
val prog: IO[List[Unit]] = names.traverse(n => IO.println(n))

parTraverse

parTraverse 是 traverse 的并行版本——每个元素的效应都会在自己的纤程上运行,非常适合并发执行 I/O,例如获取多个网址。

import cats.effect.IO
import cats.syntax.parallel._

val ids = List(1, 2, 3)
val prog: IO[List[Int]] = ids.parTraverse(id => IO(id * 10))

一个组合后的程序

这个程序读取一个值,将其加倍,然后打印结果——所有操作都由单个描述中的小型 IO 步骤组合而成。

import cats.effect.{IO, IOApp}

object Doubler extends IOApp.Simple {
  def run: IO[Unit] = for {
    n <- IO(21)
    d  = n * 2
    _ <- IO.println(s"Doubled: $d")
  } yield ()
}

普通 Scala 中的顺序执行

作为比较,下面是普通 Scala 中的顺序控制台输出——它是立即执行且非纯的,与上面的延迟 IO 版本不同。

object Main {
  def main(args: Array[String]): Unit = {
    val n = 21
    val d = n * 2
    println(s"Doubled: $d")
  }
}

快速检查

哪个方法会并发运行两个相互独立的效应,并组合它们的结果?

回顾

您使用以下方式组合了 IO 程序:

  • 使用 flatMap 和 for 按顺序执行
  • 使用 mapN / parMapN 处理相互独立的效应
  • 使用 *>、<*、void 进行组合或丢弃
  • 使用 traverse / parTraverse 处理集合

接下来:处理 IO 内部的错误。

常见问题解答

「组合 IO」课时是免费的吗?

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

「组合 IO」这节课中我会学到什么?

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

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

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

「组合 IO」课时需要多长时间?

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

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

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

此课程中的所有课时

  1. Cats 类型类
  2. IO 单子
  3. 组合 IO
  4. IO 中的错误处理
← 返回 Scala for Backend Engineering & Functional Programming