# Composing functions involving different effects

HI everyone,

say i have these two functions

``````val getUser: UserId => Future[User] = ???
``````

Is there anyway i can compose them to get? `flatMap` won’t work because the signature does not fit.

`val getUserAddress: UserId => Option[Address]`

``````val getUserAdress: UserId => Future[Adress] = userId => {
case None => Future.failed(UserNotFound)
}
}
``````
1 Like

I was actually thinking more in a generic sense. Is there any combinator that allows one to compose such functions without having to deconstruct. Something like how `map` and `flatMap` does it.

No, you can not mix two different arbitrary monads.

You either need a way to transform one into another, or keep the nesting, e.g. `Future[Option[A]]`

1 Like

Thank you. I was just curious is there a way to do it and i don’t know about it.

Cats has the `Nested` datatype which makes it easier to work with nested effects.

1 Like

Yeah but it stop at Applicative once you want to `flatMap` you need an specific monad transformer.

Anyways, I bleiev OP’s point is not how to deal with nested effects, but it if was a common function for something like:

``````def flatMapG[F[_], G[_], A, B](fa: F[A])(f: A => G[B]): F[B]
``````

Which AFAIK there isn’t (in the general sense). But well, I am actually not that versed on cats; or category theory overall.

In scalaz terminology, a conversion between different `F[_]`s and `G[_]`s is called a NaturalTransformation.

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 `for` comp.

If you have questions about this stuff get on Cats gitter and plenty of people there can help.

``````import cats._
import cats.data._
import cats.implicits._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

val getUser: UserId => Future[User] = ...

def getUser2(uid: UserId): OptionT[Future, User]  = OptionT.liftF(getUser(uid))

def composed(uid: UserId): OptionT[Future, Address] =
for {
u <- getUser2(uid)
} yield a

``````
3 Likes

@laiboonh here is a very simple example of using OptionT that you may want to use as a stepping stone to warm up on OptionT before looking at @tpolecat’s example, which is the definitive answer to your question:

``````import cats.data.OptionT
import cats.implicits._
import org.specs2.concurrent.ExecutionEnv
import org.specs2.execute.Result
import org.specs2.mutable.Specification

import scala.concurrent.Future

class Temp(implicit ee: ExecutionEnv) extends Specification {

"OptionT" should {
"allow me to treat Future[Option[Int]] as a monad" in test
}

def test: Result = {

val futureMaybeX : Future[Option[Int]] = Future.successful(Some(3))
val futureMaybeY : Future[Option[Int]] = Future.successful(Some(5))
val futureMaybeZ : OptionT[Future, Int] =
for {
x <- OptionT(futureMaybeX)
y <- OptionT(futureMaybeY)
} yield x + y

futureMaybeZ.value must beSome(8).await
}

}
``````
1 Like

@laiboonh if you want to know more about monad transformers, I found the following video useful: Options in Futures, how to unsuck them.