2
votes

In the Scala with Cats:

import scala.concurrent.{Future, ExecutionContext}
implicit def futureFunctor
  (implicit ec: ExecutionContext): Functor[Future] = …

Whenever we summon a Functor for Future , either directly using Functor.apply or indirectly via the map extension method, the compiler will locate futureFunctor by implicit resolu on and recursively search for an ExecutionContext at the call site. This is what the expansion might look like:

// We write this:
Functor[Future]
// The compiler expands to this first:
Functor[Future](futureFunctor)
// And then to this:
Functor[Future](futureFunctor(executionContext))

Ok, I try it:

  import scala.concurrent.{Future, ExecutionContext}
  implicit def futureFunctor
  (implicit ec: ExecutionContext): Functor[Future] = new Functor[Future] {
    override def map[A, B](fa: Future[A])(f: A => B): Future[B] =fa map f
  }

  Functor[Future].map(Future.successful(2))(_+1)

But get an exception:

Error:(29, 10) could not find implicit value for parameter instance: cats.Functor[scala.concurrent.Future]
Functor[Future].map(Future.successful(2))(_+1)

Which I would usually fix as:

import cats.instances.future._

But the fix does not help. And I must not import it, cause in the scope implicit futureFunctor already defined.

What do I miss?

1

1 Answers

7
votes

But get an exception:

This is not an exception, this is a compile error.

When you write implicit def futureFunctor(implicit ec: ExecutionContext) = ... this means there should be an ExecutionContext in scope. But there wasn't when you called Functor[Future] in Functor[Future].map(Future.successful(2))(_+1).

Try

import scala.concurrent.ExecutionContext.Implicits.global

or

implicit val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))

or something similar.

By the way, if you import cats.instances.future._ and define your local Functor[Future] it seems the cat's one will be used.