TimedFuture

The TimedFuture effect is a thin shim on top of Scala’s Future. The only extra capability it has built-in is timeouts, which are supported by passing in a ScheduledExecutionContext. Note that because Future represents a computation already taking place, TimedFuture is a function that returns a Future. This means if you start a computation before passing the Future into Eff, the Future will begin less predictably.

Now, let’s create some TimedFuture effects:

import org.atnos.eff._
      import org.atnos.eff.future._
      import org.atnos.eff.syntax.all._
      import org.atnos.eff.concurrent.Scheduler

      import scala.concurrent._, duration._
      import scala.concurrent.ExecutionContext.Implicits.global

      type R = Fx.fx2[TimedFuture, Option]

      val action: Eff[R, Int] =
        for {
          // create a value now
          a <- Eff.pure[R, Int](1)

          // evaluate a value later, on some other thread pool, and continue when it's finished
          b <- futureDelay[R, Int](1)
        } yield b

Then we need to pass a Scheduler and an ExecutionContext in to begin the computation.


      implicit val scheduler: Scheduler = ExecutorServices.schedulerFromGlobalExecutionContext
      import org.atnos.eff.syntax.future._

      Await.result(action.runOption.runSequential, 1.second)

> Some(1)

You can also use other Future or Task effects:

There are corresponding syntax imports to be able to call runAsync methods in:

Future and Task computations can also be memoized to avoid expensive computations to be done several times. You can either

import cats.syntax.all._
      import org.atnos.eff._, future._, all._
      import org.atnos.eff.concurrent.Scheduler
      import org.atnos.eff.syntax.all._
      import org.atnos.eff.syntax.future._
      import scala.concurrent._, duration._
      import scala.concurrent.ExecutionContext.Implicits.global

      var i = 0

      def expensive[R: _Future: _memo]: Eff[R, Int] =
        futureMemoized[R, Int]("key", futureDelay[R, Int] { i += 1; 10 * 10 })

      type S = Fx.fx2[Memoized, TimedFuture]

      implicit val scheduler: Scheduler = ExecutorServices.schedulerFromGlobalExecutionContext

      val futureMemo: Future[Int] =
        (expensive[S] >> expensive[S]).runFutureMemo(ConcurrentHashMapCache()).runSequential

      Await.result(futureMemo, 1.second)

      "there is only one invocation" <==> (i === 1)

> there is only one invocation <=> true