在理解中混合 Future 和 F[]

Moj*_*ojo 0 scala scala-cats

我在理解上遇到了问题,如下所示:


  def doSomething(): F[String] = {

    for {
      _ <- Future.traverse(items)(item => doSomeWork(item)) // Future[]
      _ <- doSomeOtherWork(42)  //F[]
    } yield (())

  }

Run Code Online (Sandbox Code Playgroud)

该函数doSomeWork看起来像:

  def doSomeWork(item: Item): Future[Unit] =
         // some work done inside a Future
    )
Run Code Online (Sandbox Code Playgroud)

功能doSomeOtherWork工作如下:

    def doSomeOtherWork(i : Int): F[Unit]
Run Code Online (Sandbox Code Playgroud)

因此,当我尝试编译时,遇到以下错误:

[error]  found   : F[Int]
[error]  required: scala.concurrent.Future[?]
[error]       
[error]         ^
[error] type mismatch;
[error]  found   : scala.concurrent.Future[Nothing]
[error]  required: F[Int]

Run Code Online (Sandbox Code Playgroud)

我不允许在这样的 for comp 中混合 F[] 和 Future 吗?

Lui*_*rez 5

不,你不能。
A for comprehension只是调用& 的语法糖。而那些只适用于同一个 monad。flatMapmap

如果你不能改变doSomeWork返回一个F,你能做的最好的事情就是将你的期货转换Fs为 for。

这是您如何做到这一点的示例。
(我不得不发明很多细节,因为你的问题很模糊)

import cats.effect.{Async, ContextShift, Sync}
import cats.instances.list._ // Provides the Foldable[List] instance into scope.
import cats.syntax.flatMap._ // Provides the flatMap method (used in the for).
import cats.syntax.foldable._ // Provides the traverse_ method.
import cats.syntax.functor._ // Provides the map method (used in the for).
import scala.concurrent.Future

final case class Item(id: Int, name: String)

def doSomeWork(item: Item): Future[Unit] = ???

def doSomeOtherWork[F[_] : Sync](i: Int): F[Unit] = ???

def doSomething[F[_]](items: List[Item])(implicit F: Async[F], cs: ContextShift[F]): F[Unit] =
  for {
    _ <- items.traverse_(item => Async.fromFuture(F.delay(doSomeWork(item))))
    _ <- doSomeOtherWork(42)
  } yield ()
Run Code Online (Sandbox Code Playgroud)

猫效果 测试2.0.0