如何使用遍历 运行 效果列表

How To Use Traverse To Run A List of Effects

我有这样的功能:

 def getFile(url: String): EitherT[Future, Error, ByteString]

这是使用猫 EitherT。

我使用另一个函数调用此函数,如下所示:

def getAllFiles(urls: List[String]): EitherT[Future, Error, List[ByteString]] = {
    urls.map(f => getFile(f).value)
  }

这不起作用,因为我发现类型不匹配:

found   : List[scala.concurrent.Future[Either[Error,akka.util.ByteString]]]
[error]  required: cats.data.EitherT[scala.concurrent.Future,Error,List[akka.util.ByteString]]

无论我尝试什么,我都无法编译。基本上我想做的是 运行 为每个 URL getFile 并在 Bytestring.

中下载文件

这个有效:

import cats.data.EitherT
import cats.effect.IO
import cats.implicits._

type Error = String
type ByteString = Array[Byte]

def getFile(url: String): EitherT[IO, Error, ByteString] = ???

def getAllFiles(urls: List[String]): EitherT[IO, Error, List[ByteString]] =
  urls.traverse(getFile)

但这不是:

def getFile(url: String): EitherT[Future, Error, ByteString] = ???

def getAllFiles(urls: List[String]): EitherT[Future, Error, List[ByteString]] =
  urls.traverse(getFile)

原因是 traverse 期望来自嵌套效果的 ApplicativecatsIO 但不适用于 Future.


所以,原因是由于 Future 的急切和缓存性质,我们无法真正推断其行为。所以 cats 没有为它提供实例。
您可以为 Future 提供自己的 Applicative...但是,恕我直言,使用 IO.fromFutureio.unsafeToFuture() 调整代码会更容易