使用scala.concurrent.Future与EitherT时缺少Functor和Monad实例

时间:2015-12-22 01:34:07

标签: scala monad-transformers scalaz7

我正在尝试将Scalaz EitherT与scala.concurrent.Future一起使用。当试图在for-comprehension中使用它时:

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

我得到以下缺少的Functor和Monad实例错误:

days = WebtmsDay.arel_table
other_days = days[:day].not_in(['Monday', 'Tuesday', 'Thursday'])

WebtmsClass.where(WebtmsDay.where(other_days).exists.not)

scalaz是否定义了Functor和Monad for Future的实例?如果没有提供这些实例的其他库或我是否需要编写它们?

2 个答案:

答案 0 :(得分:15)

您需要在范围内隐式ExecutionContextimport 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")

答案 1 :(得分:0)

该错误不是由于缺少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)