Search code examples
scalafunctional-programmingscalazzio

Composing Multiple Futures and Option in Scala with ZIO


I just started evaluating ZIO to improve the programming model and the performance of my asynchronous Scala code. In my code base I deal with Future[Option[T]] often, and to this point I have dealt with that using Scalaz's OptionT monad transformer. Now I want to try this with ZIO.

Consider two functions:

def foo: String => Future[Option[T]] and def bar: T => Future[U]

I tried something like this:

val t = for {
       o: Option[Int] <- ZIO.fromFuture { implicit ec =>
            foo("test")
       }
       i: Int <- ZIO.fromOption(o)
       s: String <- ZIO.fromFuture { implicit ec =>
            bar(i)
       }
} yield s

According to my IDE, t is of type ZIO[Any, Any, String] in this scenario. I don't know what to do with that.

I want to consider three possibilities:

  • The "success" case where foo produces a Some that can be composed with other functions on the value
  • The case where foo produces a None
  • The case where either function produces an error

I am not sure how to parse those possibilities in this scenario with ZIO. Any help is appreciated.


Solution

  • There are couple operators that can help you out in this case, basically instead of explicitly unwrapping the Option with fromOption, I would recommend using a combination of some and asSomeError

    val t: Task[Option[String]] = (for {
    
      // This moves the `None` into the error channel
      i: Int <- ZIO.fromFuture(implicit ec => foo("test")).some
    
      // This wraps the error in a Some() so that the signature matches
      s: String <- ZIO.fromFuture(implicit ec => bar(i)).asSomeError
    
    } yield s).optional // Unwraps the None back into the value channel