缺少 Cats Functor[Future] 实例

missing Cats Functor[Future] instance

我正在尝试使用 OptionT 来组合返回 Future[Option[T]] 的方法以进行理解。

import cats.data._
import cats.implicits._
import cats.instances.future._

for {
  data <- OptionT(repo.getData(id))
  ... 
}

我得到的编译器错误:

could not find implicit value for parameter F cats.Functor[scala.concurrent.Future]

recent example 表明这是(曾经?)可能的。

pull request for adding OptionT

中的文档也是如此

cats Functor docs

我在这里错过了什么?

谢谢

通过导入 cats.implicits._,您实际上已经导入了 cats.syntax.AllSyntaxcats.instances.AllInstances

尝试只使用那些导入:

import cats.data._
import cats.implicits._

或(根据您的需要):

import cats.data._
import cats.instances.future._

或更具体地说:

import cats.data._
import cats.instances.future.catsStdInstancesForFuture

您可能还需要:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

注意:当然你必须在生产环境中隐含地提供一个实际的ExecutionContext

以下导入对我有用( 中也提到),

import cats.data.OptionT
import cats.instances.future._ // or import cats.implicits._ 
                               // as implicits include FutureInstances

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

此外,重要的是依赖关系,因为我使用 org.typelevel:cats:0.9.0cats-core-1.1.0 导致 Symbol 'type cats.kernel.instances.EqInstances' is missing from the classpath.

不得不删除旧的 cats-0.9.0 并使用最新的 cats-core and cats-kernel

libraryDependencies ++= Seq(
  "org.typelevel" %% "cats-core" % "1.1.0",
  "org.typelevel" %% "cats-kernel" % "1.2.0",

  "org.scalatest" %% "scalatest" % "3.0.4" % Test
)

有同样的问题。 cats居然有实例

真正的问题只是隐含的 ExecutionContext 缺失,您可以执行以下操作

import scala.concurrent.ExecutionContext.Implicits.global

我在尝试为其提供实例时意识到了这一点。

    implicit val ev: Functor[Future] = new Functor[Future] {
      override def map[A, B](fa: Future[A])(f: A => B): Future[B] = fa.map(f)
    }

此时编译器会说缺少 implicit ExecutionContext

看起来这个问题的原因可能是多种多样的;我只是 运行 进入这个,因为我在范围内有两个隐式 ExecutionContexts 可用,所以猫无法 select 一个提供 Functor[Future]:

import scala.concurrent.ExecutionContext.Implicits.global
// ^ first implicit ExecutionContext

class MyClass {
  def myMethod(e: EitherT[Future, _, _])(implicit ec: ExecutionContext) {
    // Second implicit ExecutionContext
    e.flatMap(...) // <- Functor unavailable
  }
}

在我的例子中,我能够通过简单地不将 ec 传递给 myMethod 来解决问题,尽管删除全局执行上下文也会起作用。