我想使用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来做类似的事情,但是无法弄清楚它的精确程度。任何帮助将不胜感激。
答案 0 :(得分: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 {
???
}
}