Cats Effect IO:将Scala集合与IO组合在一起

时间:2018-12-11 18:32:49

标签: scala functional-programming scala-cats cats-effect

这是一个玩具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)

我在做什么错了?

1 个答案:

答案 0 :(得分:2)

您的理解力适合您的IO,但您正在将其与List混在一起。为了更清楚一点,我们可以扩展for理解,因为您无法将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仅将mapsequence步骤压缩为一个。无论哪种情况,现在您的理解力都仅限于IO