Monads don’t compose in general (and this is what you need because you’re composing effectful functions end to end), but in this case you can compose them with the
OptionT monad transformer, basically by massaging both result types into
Future[Option[A]] and then wrapping up in
OptionT to yield a composed effect type
OptionT[Future, A]. This type is a monad and you can compose with
flatMap or a
If you have questions about this stuff get on Cats gitter and plenty of people there can help.
val getUser: UserId => Future[User] = ...
val getAddress: User => Option[Address] = ...
def getUser2(uid: UserId): OptionT[Future, User] = OptionT.liftF(getUser(uid))
def getAddress2(usr: User): OptionT[Future, Address] = OptionT.fromOption(getAddress(usr))
def composed(uid: UserId): OptionT[Future, Address] =
u <- getUser2(uid)
a <- getAddress2(u)
} yield a
composed(...).value // Future[Option[Address]]