Convert Future instances to cats-effect IO
Dev interested in functional programming solutions for Scala.
Much (most?) of the third-parties software that you will have to deal with will not handle asynchronous actions using our beloved IO monad, they will instead use either Scala’s or Java’s Future. This brief entry shows how to convert those Futures into IO instances.
Scala
FuturetoIO: actually this is pretty straightforward, just useIO.fromFuture:import cats.effect.IO import scala.concurrent.IO IO.fromFuture( IO(Future.successful("Scala Future converted to CE IO successfully")) )Java
CompletableFuturetoIO: as easy as runningIO.fromCompletableFuture:import cats.effect.IO import java.util.concurrent.CompletableFuture IO.fromCompletableFuture( IO(CompletableFuture.completedFuture("Java CompletableFuture converted to CE IO successfully")) )Java
FuturetoIO, this is unfortunately more convoluted. There is no a straightforward method to do this. Instead we will create a new method that periodically checks if theFutureinstance is completed and if so it returns its value, otherwise it sleeps (waits) and retries again. Note that the sleep call only blocks the fiber 'semantically', that is, the actual thread is not blocked. So this is a cheap method to execute. This method is a simplified version of this gist from Gavin Bisesi (Daenyth), which I encourage you to take a look. This is how we can define and use the method:import cats.effect.IO import java.util.concurrent.{CompletableFuture, Future => JFuture} // Convert a Java Future into an IO def convertToIO[A](fa: => JFuture[A]): IO[A] = IO.delay(fa.isDone).flatMap: isDone => if (isDone) IO.delay(fa.get) // Future done, return the result else IO.sleep(5.milliseconds) >> convertToIO(fa) // Retry again in a little while // Dummy creation of a dummy Java Future val createJavaFuture: IO[JFuture[String]] = IO{ val cf = new CompletableFuture[String]() cf.complete("Java Future converted to CE IO successfully") cf } createJavaFuture >>= convertToIO
So, that's all!
All code in this blog entry can be found in this gist. You can run it using scala-cli:
$ scala-cli FutureToIO.scala
Or by invoking the gist itself from scala-cli:
$ scala-cli https://gist.github.com/lrodero/4ae172a75b8a8d5bf72cba1890e3ac5f


