We could try to use the Async type class to model the kind of effects that can be executed concurrently.
Async is a Monad that can describe asynchronous or synchronous computations that produce exactly one result.
The first data type that we can think of is cats.effect.IO
but the key aspect to keep in mind is that
either a Future or an IO might be synchronous/blocking operations.
IO.delay{ ... }
// same as
IO { ... }
IO { ... }
does NOT make anything async (see IO.apply)- does NOT switch threads
- creates simple IO values from synchronous side-effecting APIs
- to force a "context shift" to another Execution Context we can take advantage of
IO.shift
A very interesting discussion about this subject is this SO answer.
It's not possible to write an instance of
Async
forFuture
that has the right semantics, becauseAsync
extendsSync
, andSync
requires a representation of a computation that can be run repeatedly, while Scala's futures begin running when they're defined and can't be re-run (eagerly evaluated).
Via SO answer (Async[Future]
)
Nevertheless, it's possible to get a generic HKT effect from Future:
import cats.effect.{Async, ContextShift]
def toF[F[_] : Async : ContextShift]: F[Result] =
Async.fromFuture(Async[F].delay(functionReturningFuture(x)))
Via SO answer