将 scala.concurrent.Future 与 EitherT 一起使用时缺少 Functor 和 Monad 实例
Missing Functor and Monad instances when using scala.concurrent.Future with EitherT
我正在尝试将 Scalaz EitherT 与 scala.concurrent.Future 一起使用。当试图在理解中使用它时:
import scalaz._
import Scalaz._
val et1:EitherT[Future, String, Int] = EitherT(Future.successful(1.right))
val et2:EitherT[Future, String, String] = EitherT(Future.successful("done".right))
val r:EitherT[Future, String, String] = for {
a <- et1
b <- et2
} yield (s"$a $b")
我收到以下缺少 Functor 和 Monad 实例的错误:
could not find implicit value for parameter F: scalaz.Functor[scala.concurrent.Future]
b <- et2
^
could not find implicit value for parameter F: scalaz.Monad[scala.concurrent.Future]
a <- et1
scalaz 是否为 Future 定义了 Functor 和 Monad 的实例?如果没有,是否有任何其他库提供这些实例,或者我是否需要编写它们?
您需要一个隐含的 ExecutionContext
作用域。 import ExecutionContext.Implicits.global
会给你 global execution context.
完整示例:
import scala.concurrent.ExecutionContext.Implicits.global
import scalaz._
import Scalaz._
val et1:EitherT[Future, String, Int] = EitherT(Future.successful(1.right))
val et2:EitherT[Future, String, String] = EitherT(Future.successful("done".right))
val r:EitherT[Future, String, String] = for {
a <- et1
b <- et2
} yield s"$a $b"
val foo = Await.result(r.run, 1 seconds)
// => \/-("1 done")
错误不是因为缺少 ExecutionContext(尽管它是必需的),而是因为 Scala Future 既不是 Functor 也不是 Monad。
接受的解决方案之所以有效,不是因为 ExecutionContext,而是因为它从 Scalaz 导入了所有隐式。
这是真正解决问题的行:
import Scalaz._
另请注意,使用全局执行上下文可以用于测试,但不应用于生产部署。
该解决方案的问题是您导入了库中定义的所有隐含函数,这会使您的 IDE 有点慢。
在版本 7 中,Scalaz 提供了仅导入您需要的选项,使用包 scalaz.syntax
。
与之前的具体导入解决方案相同:
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scalaz._
import scalaz.std.scalaFuture._
import scalaz.syntax.either._
val et1:EitherT[Future, String, Int] = EitherT(Future.successful(1.right))
val et2:EitherT[Future, String, String] = EitherT(Future.successful("done".right))
val r:EitherT[Future, String, String] = for {
a <- et1
b <- et2
} yield s"$a $b"
val foo = Await.result(r.run, 1 seconds)
foo: String \/ String = \/-(1 done)
我正在尝试将 Scalaz EitherT 与 scala.concurrent.Future 一起使用。当试图在理解中使用它时:
import scalaz._
import Scalaz._
val et1:EitherT[Future, String, Int] = EitherT(Future.successful(1.right))
val et2:EitherT[Future, String, String] = EitherT(Future.successful("done".right))
val r:EitherT[Future, String, String] = for {
a <- et1
b <- et2
} yield (s"$a $b")
我收到以下缺少 Functor 和 Monad 实例的错误:
could not find implicit value for parameter F: scalaz.Functor[scala.concurrent.Future]
b <- et2
^
could not find implicit value for parameter F: scalaz.Monad[scala.concurrent.Future]
a <- et1
scalaz 是否为 Future 定义了 Functor 和 Monad 的实例?如果没有,是否有任何其他库提供这些实例,或者我是否需要编写它们?
您需要一个隐含的 ExecutionContext
作用域。 import ExecutionContext.Implicits.global
会给你 global execution context.
完整示例:
import scala.concurrent.ExecutionContext.Implicits.global
import scalaz._
import Scalaz._
val et1:EitherT[Future, String, Int] = EitherT(Future.successful(1.right))
val et2:EitherT[Future, String, String] = EitherT(Future.successful("done".right))
val r:EitherT[Future, String, String] = for {
a <- et1
b <- et2
} yield s"$a $b"
val foo = Await.result(r.run, 1 seconds)
// => \/-("1 done")
错误不是因为缺少 ExecutionContext(尽管它是必需的),而是因为 Scala Future 既不是 Functor 也不是 Monad。
接受的解决方案之所以有效,不是因为 ExecutionContext,而是因为它从 Scalaz 导入了所有隐式。
这是真正解决问题的行:
import Scalaz._
另请注意,使用全局执行上下文可以用于测试,但不应用于生产部署。
该解决方案的问题是您导入了库中定义的所有隐含函数,这会使您的 IDE 有点慢。
在版本 7 中,Scalaz 提供了仅导入您需要的选项,使用包 scalaz.syntax
。
与之前的具体导入解决方案相同:
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scalaz._
import scalaz.std.scalaFuture._
import scalaz.syntax.either._
val et1:EitherT[Future, String, Int] = EitherT(Future.successful(1.right))
val et2:EitherT[Future, String, String] = EitherT(Future.successful("done".right))
val r:EitherT[Future, String, String] = for {
a <- et1
b <- et2
} yield s"$a $b"
val foo = Await.result(r.run, 1 seconds)
foo: String \/ String = \/-(1 done)