Cats Effect IO:使用 Scala 集合组合 IO
Cats Effect IO: Compose IO with Scala collections
这是一个玩具 Scala 程序,它从控制台读取 10 个数字并将每个数字加 1 打印出来:
import cats._
import cats.effect._
import cats.implicits._
object Main extends IOApp {
def printLine[A](x: A)(implicit show: Show[A]): IO[Unit] =
IO(println(show.show(x)))
def readLine(): IO[String] =
IO(scala.io.StdIn.readLine())
def readInts(n: Int): IO[List[Int]] =
List.fill(n)(readLine().map(_.toInt)).sequence
override def run(args: List[String]): IO[ExitCode] = {
for {
list <- readInts(10)
i <- list
_ <- printLine(i + 1)
} yield ExitCode.Success
}
}
以上代码无法编译。我得到:
[error] found : cats.effect.IO[cats.effect.ExitCode]
[error] required: scala.collection.GenTraversableOnce[?]
[error] _ <- printLine(i + 1)
我做错了什么?
您的理解是针对您的 IO
,但您将其与 List
混为一谈。为了更清楚一点,我们可以扩展 for comprehension,它不会编译,原因与您不能将 List
展平为 IO
:
的原因相同
readInts(10).flatMap(list => list.flatMap(i => printLine(i + 1).map(_ => ExitCode.Success)))
相反,试试这个:
for {
list <- readInts(10)
_ <- list.traverse(i => printLine(i + 1))
} yield ExitCode.Success
请注意,这与以下内容基本相同:
for {
list <- readInts(10)
_ <- list.map(i => printLine(i + 1)).sequence
} yield ExitCode.Success
traverse
只是将 map
和 sequence
步骤压缩为一个。无论哪种情况,现在您的理解都正确地限制在 IO
.
这是一个玩具 Scala 程序,它从控制台读取 10 个数字并将每个数字加 1 打印出来:
import cats._
import cats.effect._
import cats.implicits._
object Main extends IOApp {
def printLine[A](x: A)(implicit show: Show[A]): IO[Unit] =
IO(println(show.show(x)))
def readLine(): IO[String] =
IO(scala.io.StdIn.readLine())
def readInts(n: Int): IO[List[Int]] =
List.fill(n)(readLine().map(_.toInt)).sequence
override def run(args: List[String]): IO[ExitCode] = {
for {
list <- readInts(10)
i <- list
_ <- printLine(i + 1)
} yield ExitCode.Success
}
}
以上代码无法编译。我得到:
[error] found : cats.effect.IO[cats.effect.ExitCode]
[error] required: scala.collection.GenTraversableOnce[?]
[error] _ <- printLine(i + 1)
我做错了什么?
您的理解是针对您的 IO
,但您将其与 List
混为一谈。为了更清楚一点,我们可以扩展 for comprehension,它不会编译,原因与您不能将 List
展平为 IO
:
readInts(10).flatMap(list => list.flatMap(i => printLine(i + 1).map(_ => ExitCode.Success)))
相反,试试这个:
for {
list <- readInts(10)
_ <- list.traverse(i => printLine(i + 1))
} yield ExitCode.Success
请注意,这与以下内容基本相同:
for {
list <- readInts(10)
_ <- list.map(i => printLine(i + 1)).sequence
} yield ExitCode.Success
traverse
只是将 map
和 sequence
步骤压缩为一个。无论哪种情况,现在您的理解都正确地限制在 IO
.