为什么添加import`import cats.instances.future._`将导致隐式Functor [Future]的编译错误

时间:2018-02-20 13:10:27

标签: scala compilation future functor scala-cats

scala代码正在使用猫并且效果很好:

mquadri$ python3 -m timeit -s "from bisect import bisect" "my_range = list(range(97, 123));  my_range.insert(bisect(my_range, 32), 32)"
1000000 loops, best of 3: 1.18 usec per loop

但是如果我添加这个导入:

import cats.implicits._
import cats.Functor
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

object Hello extends App {

  Functor[Future].map(Future("hello"))(_ + "!")

}

它将报告此类编译错误:

import cats.instances.future._

为什么会发生这种情况,我如何调试它以找到原因?我用各种各样的方法,但找不到任何东西。

Error:(18, 10) could not find implicit value for parameter instance: cats.Functor[scala.concurrent.Future] Functor[Future].map(Future("hello"))(_ + "!") 文件是:

build.sbt

2 个答案:

答案 0 :(得分:4)

对象cats.implicitsFutureInstances trait作为线性超类型。 FutureInstances具有隐式catsStdInstancesForFuture方法,该方法生成Monad[Future],而Functor[Future]又为FutureInstances

另一方面,对象cats.instances.future 混合在catsStdInstancesForFuture中,因此它再次提供隐式方法Functor[Future],但通过另一条路径。< / p>

现在编译器有两种可能性来生成cats.instances.future.catsStdInstancesForFuture

  • 通过调用cats.implicits.catsStdInstancesForFuture
  • 通过调用cats.implicits._

由于它无法决定采取哪一个,因此会退出并显示错误消息。

为避免这种情况,请勿将cats.instances.future._`import packagename.objectname.{member1name, member2name}` 一起使用。省略其中一个导入,或使用

"-print"

仅选择您需要的那些内容。

调试隐含时,

scalacOptions添加到scalacOptions ++= Seq( ... "-print", ... ) 可以帮助:

cats.implicits.

它将使用cats.instances.Functor[Future]打印出去掉的代码。不幸的是,它往往会产生很多噪音。

发生这种情况的更根本原因是,没有办法在导致{{1}的两条(等效)途径之间定义更高维度的细胞(#34; homotopies&#34;) }}。如果我们有可能告诉编译器哪个路径并不重要,那么一切都会好得多。由于我们无法做到这一点,因此我们必须确保始终只有一种方法可以生成隐式Functor[Future]

答案 1 :(得分:2)

问题是实例导入了两次,这意味着scalac无法消除它们之间的歧义,也不知道使用哪一个然后失败。

因此,要么使用implicits._导入,要么使用instances.<datatype>._导入特定实例,但不要同时导入两者!

您可以在此处深入了解猫的进口情况:https://typelevel.org/cats/typeclasses/imports.html