将IO列表转换为列表的IO

问题描述 投票:0回答:1

我想用cats-effect的IO monad读取一个文件列表,如下所示:

def readFile(file: File): IO[Either[CouldNotReadFromFileError, String]] = ???

// lists all the files I want to read
// returns an Either b/c this might encounter i/o problems
def findFiles(): IO[Either[Throwable, Array[File]]] = ???

// reads all files and saves their content in an Array[String]
// ignores files it could not read or find
def readFiles(): IO[Array[String]] = for {
    filesE <- listFiles
    files = filesE match {
      case Left(err) =>
        log.error("An error happened while reading files: " + err.getMessage)
        List[File]()
      case Right(fs) => fs.toList.map(readFile)
    }
    // files has type: List[IO[Either[CouldNotReadFromFileError, String]]]
    // to continue here I'd like to have a: IO[List[Either[CouldNotReadFromFileError, String]]]
    ???
} yield ???

现在继续我在for-yield-construction中的计算我想把我的List[IO[Either[CouldNotReadFromFileError, String]]]变成一个IO[List[Either[CouldNotReadFromFileError, String]]]。我知道我可以使用cat's traverse做这样的事情,但无法弄清楚究竟是怎么回事。任何帮助是极大的赞赏。

scala io functional-programming scala-cats
1个回答
1
投票

sequence足以满足您的需求:

import java.io.File
import cats.effect.IO
import cats.implicits._

final class CouldNotReadFromFileError extends RuntimeException("message")

object TestTest {
  def readFile(file: File): IO[Either[CouldNotReadFromFileError, String]] = ???

  def findFiles: IO[Either[Throwable, Array[File]]] =
    ???

  // reads all files and saves their content in an Array[String]
  // ignores files it could not read or find
  def readFiles(): IO[Array[String]] =
    for {
      filesE <- findFiles
      files = filesE match {
        case Left(err) =>
          List.empty
        case Right(fs) =>
          fs.toList.map(readFile)
      }
      // The type ascription below is just for demonstration purposes.
      // You don't need to keep it there.
      a <- files.sequence: IO[List[Either[CouldNotReadFromFileError, String]]]
    } yield {
      ???
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.