我在理解上遇到了问题,如下:
def doSomething(): F[String] = {
for {
_ <- Future.traverse(items)(item => doSomeWork(item)) // Future[]
_ <- doSomeOtherWork(42) //F[]
} yield (())
}
函数doSomeWork
看起来像:
def doSomeWork(item: Item): Future[Unit] =
// some work done inside a Future
)
并且函数doSomeOtherWork
的工作类似于:
def doSomeOtherWork(i : Int): F[Unit]
因此,当我尝试编译时,出现以下错误:
[error] found : F[Int]
[error] required: scala.concurrent.Future[?]
[error]
[error] ^
[error] type mismatch;
[error] found : scala.concurrent.Future[Nothing]
[error] required: F[Int]
我不允许在这样的comp中混合F []和Future吗?
不,这是不可能的。因为for理解只是map和flatMap调用的语法糖,所以您的程序实际上如下所示:
(_: Future[Int]).flatMap(doSomeOtherWork).map(())
并且由于Future.flatMap
期望函数再次返回Future,所以程序将被编译器拒绝。
不,你不能。用于理解只是用于调用flatMap
和map
的糖语法。而那些只能在同一单子上工作。
[如果无法更改doSomeWork
以返回F
,您可以做的最好的就是将您的期货转换为上的Fs
。
这里是您可能如何执行此操作的示例。((我不得不发明许多细节,因为您的问题非常含糊)
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 ()
使用cats-effect 2.0.0
测试。