将Scala 2.10 Future转换为Scalaz.concurrent.Future // Task

12

有没有人提供一些代码来正确地将Scala 2.10的Future转换为新的Scalaz7 Future?我知道如何通过Scala Promise将Scalaz Future转换为Scala Future,但不确定如何正确地处理它。

例如:

import scalaz.concurrent.{Future => Zuture}
import scala.concurrent.Future

我希望你能够实现

implicit def scalaF2scalazF[A](in:Future[A]):Zuture[A]=???

那么显然很容易写出来

implicit def scalaF2scalazTask[A](in:Future[A]):Task[A]=???

因为那是我真正想要的 :-)


你看过 scalaz-contrib 库吗?那里有一些 scala.concurrent.Future 的实例。 - George
感谢您的指出。然而,我理解这些是将Scala Futures转换为Scalaz Monad / Monoids / Semigroups。不确定如何在使用Tasks / Scalaz.Future的代码片段中使用它。您能否提供一个小的代码示例,说明如何将硬编码任务(即Scalaz-Stream)与使用Scala Future(即Play迭代器)的任务链接起来? - Pavel Chlupacek
2个回答

21
在评估了几种替代方案后,我得出了以下解决方案。显然,如果有人需要scalaz.Monad[scala.concurrent.Future]scalaz.std.scalaFuturehttps://github.com/scalaz/scalaz/blob/series/7.2.x/core/src/main/scala/scalaz/std/Future.scala#L85是可行的方法。
object ScalaFutureConverters {


  implicit def scalaFuture2scalazTask[T](fut: Future[T])(implicit ec: ExecutionContext): Task[T] = {
    Task.async {
      register =>
        fut.onComplete {
          case Success(v) => register(v.right)
          case Failure(ex) => register(ex.left)
        }
    }
  }


  implicit def scalazTask2scalaFuture[T](task: Task[T]): Future[T] = {
    val p: Promise[T] = Promise()

    task.runAsync {
      case -\/(ex) => p.failure(ex)
      case \/-(r) => p.success(r)
    }

    p.future
  }


  implicit class ScalazFutureEnhancer[T](task: Task[T]) {
    def asScala: Future[T] = scalazTask2scalaFuture(task)
  }


  implicit def scalaF2EnhancedScalaF[T](fut: Future[T])(implicit ec: ExecutionContext): ScalaFEnhancer[T] =
    ScalaFEnhancer(fut)(ec)

  case class ScalaFEnhancer[T](fut: Future[T])(implicit ec: ExecutionContext) {
    def asTask: Task[T] = scalaFuture2scalazTask(fut)(ec)
  }

}

然而,这种解决方案在将任务转换为Scala Future后也会运行该任务,这可能是需要的或不需要的,具体取决于情况。


4
答案开头的链接现在已经失效。 - jedesah
修正了答案开头的链接。 - drstevens

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接