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.
OptionThas aMonadinstance, andMonadextendsApplywhich extendsCartesianso 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
catsSyntaxCartesianyou 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 itsApplyinstance in scope and usemap2directly (you might want to use a type alias instead of a type lambda):Alternatively, you can drop
OptionTaltogether and useApply.compose:The future will be executed in parallel in that case though, so watch out if that's not what you want.