I want to join 2 Future[Option[_]]
:
def foo: Future[Option[Int]] = ???
def baz: Future[Option[Int]] = ???
It is possible to join pair of Future
:
foo |@| baz map( (fooOpt, bazOpt) => ???)
And possible to join pair of Option
:
Option(1) |@| Option(2) map ( (a, b) => ???)
How to join pair of OptionT
? Doesn't work like that:
OptionT(foo) |@| OptionT(baz) map ( (a, b) => ???)
UPD - here is my imports:
import cats.data.OptionT
import cats.instances.future._
import cats.instances.option._
import cats.syntax.cartesian._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
EDIT
Turns out, it's a very well known issue, it is caused by SI-2712. If you add the sbt-partial-unification plugin to your project, your original code will work just fine.
As I said,
|@|
is deprecated, you should change for the following syntax:There seems to be an implicit resolution issue.
OptionT
has aMonad
instance, andMonad
extendsApply
which extendsCartesian
so your code should work indeed. It does work if you help the compiler a little bit:but if you don't specify the types for
catsSyntaxCartesian
you get an interesting error:Note that
|@|
is now deprecated but it looks like you will have the same issue with its replacementmapN
.I can think of two workarounds. If you want to use
OptionT
, then bring itsApply
instance in scope and usemap2
directly (you might want to use a type alias instead of a type lambda):Alternatively, you can drop
OptionT
altogether and useApply.compose
:The future will be executed in parallel in that case though, so watch out if that's not what you want.