Scalaz Task ↔ Scala Future

Written by Andrew Conner · Sep 25, 2015

Since many asynchronous APIs in Scala use Futures, if you prefer using Task, you’ll need to convert between the two. Here are two simple classes that enhance scalaz.concurrent.Task and scala.concurrent.Future:

import scalaz.concurrent.Task
import scala.concurrent.{ Promise, Future }

final class FutureExtensionOps[A](x: => Future[A]) {
  import scalaz.Scalaz._

  def asTask: Task[A] = {
    Task.async {
      register =>
        x.onComplete {
          case Success(v) => register(v.right)
          case Failure(ex) => register(ex.left)
        }(Implicits.trampoline)
    }
  }
}

final class TaskExtensionOps[A](x: => Task[A]) {
  import scalaz.{ \/-, -\/ }
  val p: Promise[A] = Promise()
  def runFuture(): Future[A] = {
    x.unsafePerformAsync {
      case -\/(ex) =>
        p.failure(ex); ()
      case \/-(r) => p.success(r); ()
    }
    p.future
  }
}

Provide an implicit conversion to augment Task/Future, or make these Ops implicit. There is a dependency on the trampoline ExecutionContext from Play’s iteratees library, but you can quite easily duplicate it for yourself.

Note (2016-02-01): Updated to scalaz-7.2. If using an earlier version, use runAsync instead of unsafePerformAsync.


I value your thoughts and feedback. Reach out by email or Twitter.