OptionT 的笛卡尔生成器
Cartesian builder for OptionT
我想加入 2 Future[Option[_]]
:
def foo: Future[Option[Int]] = ???
def baz: Future[Option[Int]] = ???
可以加入一对 Future
:
foo |@| baz map( (fooOpt, bazOpt) => ???)
并且可以加入一对 Option
:
Option(1) |@| Option(2) map ( (a, b) => ???)
如何连接一对OptionT
?不是那样工作的:
OptionT(foo) |@| OptionT(baz) map ( (a, b) => ???)
UPD - 这是我的导入:
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
编辑
事实证明,这是一个众所周知的问题,它是由您项目的 SI-2712. If you add the sbt-partial-unification 插件引起的,您的原始代码可以正常工作。
正如我所说,|@|
已被弃用,您应该更改为以下语法:
import cats.syntax.apply._
(OptionT(foo), OptionT(bar)).mapN(_ + _)
似乎存在隐式解析问题。 OptionT
有一个 Monad
实例,并且 Monad
extends Apply
extends Cartesian
所以你的代码应该确实有效。如果你帮助编译器一点点:
,它确实有效
import scala.concurrent.{ExecutionContext, Future}
import cats.data.OptionT
import cats.syntax.cartesian._
import cats.instances.future._
trait CartesianOptionTs {
implicit def ec: ExecutionContext
def foo: Future[Option[Int]]
def bar: Future[Option[Int]]
(catsSyntaxCartesian[({type λ[α] = OptionT[Future, α]})#λ, Int](OptionT(foo)) |@| OptionT(bar)).map(_ + _)
}
但是如果你没有为 catsSyntaxCartesian
指定类型,你会得到一个有趣的错误:
[error] found : cats.data.OptionT[scala.concurrent.Future,Int]
[error] required: ?F[?A]
[error] Note that implicit conversions are not applicable because they are ambiguous:
[error] both method ArrowAssoc in object Predef of type [A](self: A)ArrowAssoc[A]
[error] and method Ensuring in object Predef of type [A](self: A)Ensuring[A]
[error] are possible conversion functions from cats.data.OptionT[scala.concurrent.Future,Int] to ?F[?A]
[error] (catsSyntaxCartesian(OptionT(foo)) |@| OptionT(bar)).map(_ + _)
请注意,|@|
现已弃用,但看起来您在使用它的替代品 mapN
时也会遇到同样的问题。
我可以想到两个解决方法。如果要使用 OptionT
,则将其 Apply
实例带入作用域并直接使用 map2
(您可能希望使用类型别名而不是类型 lambda):
import cats.Apply
Apply[({type λ[α] = OptionT[Future, α]})#λ].map2(OptionT(foo), OptionT(bar))(_ + _)
或者,您可以完全删除 OptionT
并使用 Apply.compose
:
import cats.instances.option._
Apply[Future].compose[Option].map2(foo, bar)(_ + _)
在这种情况下,未来将并行执行,所以请注意这是否不是您想要的。
我想加入 2 Future[Option[_]]
:
def foo: Future[Option[Int]] = ???
def baz: Future[Option[Int]] = ???
可以加入一对 Future
:
foo |@| baz map( (fooOpt, bazOpt) => ???)
并且可以加入一对 Option
:
Option(1) |@| Option(2) map ( (a, b) => ???)
如何连接一对OptionT
?不是那样工作的:
OptionT(foo) |@| OptionT(baz) map ( (a, b) => ???)
UPD - 这是我的导入:
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
编辑
事实证明,这是一个众所周知的问题,它是由您项目的 SI-2712. If you add the sbt-partial-unification 插件引起的,您的原始代码可以正常工作。
正如我所说,|@|
已被弃用,您应该更改为以下语法:
import cats.syntax.apply._
(OptionT(foo), OptionT(bar)).mapN(_ + _)
似乎存在隐式解析问题。 OptionT
有一个 Monad
实例,并且 Monad
extends Apply
extends Cartesian
所以你的代码应该确实有效。如果你帮助编译器一点点:
import scala.concurrent.{ExecutionContext, Future}
import cats.data.OptionT
import cats.syntax.cartesian._
import cats.instances.future._
trait CartesianOptionTs {
implicit def ec: ExecutionContext
def foo: Future[Option[Int]]
def bar: Future[Option[Int]]
(catsSyntaxCartesian[({type λ[α] = OptionT[Future, α]})#λ, Int](OptionT(foo)) |@| OptionT(bar)).map(_ + _)
}
但是如果你没有为 catsSyntaxCartesian
指定类型,你会得到一个有趣的错误:
[error] found : cats.data.OptionT[scala.concurrent.Future,Int]
[error] required: ?F[?A]
[error] Note that implicit conversions are not applicable because they are ambiguous:
[error] both method ArrowAssoc in object Predef of type [A](self: A)ArrowAssoc[A]
[error] and method Ensuring in object Predef of type [A](self: A)Ensuring[A]
[error] are possible conversion functions from cats.data.OptionT[scala.concurrent.Future,Int] to ?F[?A]
[error] (catsSyntaxCartesian(OptionT(foo)) |@| OptionT(bar)).map(_ + _)
请注意,|@|
现已弃用,但看起来您在使用它的替代品 mapN
时也会遇到同样的问题。
我可以想到两个解决方法。如果要使用 OptionT
,则将其 Apply
实例带入作用域并直接使用 map2
(您可能希望使用类型别名而不是类型 lambda):
import cats.Apply
Apply[({type λ[α] = OptionT[Future, α]})#λ].map2(OptionT(foo), OptionT(bar))(_ + _)
或者,您可以完全删除 OptionT
并使用 Apply.compose
:
import cats.instances.option._
Apply[Future].compose[Option].map2(foo, bar)(_ + _)
在这种情况下,未来将并行执行,所以请注意这是否不是您想要的。