Cannot find a functor instance for Tuple2K

115 Views Asked by At

I have a toy DSL

case class Logging[A](msg: String, action: A)
case class Persist[A](msg: String, action: A)
type Effect[A] = EitherK[Logging, Persist, A]

that I want to pair with an equally toy interpreter

case class CoLogging[A](run: String => A)
case class CoPersist[A](run: String => A)
type Interp[A] = Tuple2K[CoLogging, CoPersist, A]

Here is an program example:

def prog(implicit L: Logs[Effect], P: Persists[Effect]): Free[Effect, Unit] =
  P.store("bar") >> L.log("foo")

and here is the interpreter:

def interpretEffect(implicit CL: CoLogs[IO], CP: CoPersists[IO]): Cofree[Interp, IO[Unit]] = 
  Cofree.unfold(IO.pure(())) { a: IO[Unit] => Tuple2K(CoLogging(CL.coLog(a)), CoPersist(CP.coPersist(a))) }

I've paid due diligence and defined functors as well as injection implicits. The compiler complains that it cannot find an instance cats.Functor[[A]cats.data.Tuple2K[example.CoLogging,example.CoPersist,A]], even though I am importing cats.data.Tuple2K._ where the instance is implicitly defined.

I can't see what I'm doing wrong, it must be something stupid. Do you have any idea? All the code can be seen in this gist.

2

There are 2 best solutions below

3
On BEST ANSWER

The compiler complains that it cannot find an instance cats.Functor[[A]cats.data.Tuple2K[example.CoLogging,example.CoPersist,A]], even though I am importing cats.data.Tuple2K._ where the instance is implicitly defined.

Functor[Tuple2K[F, G, ?]] is defined via Tuple2KInstances8#catsDataFunctorForTuple2K if Functor[F] and Functor[G] were defined. The thing is that Functor[CoLogging] and Functor[CoPersist] weren't.

Add

object CoLogging {
  implicit val coLoggingFunctor: Functor[CoLogging] = new Functor[CoLogging] {
    override def map[A, B](fa: CoLogging[A])(f: A => B): CoLogging[B] = CoLogging(fa.run andThen f)
  }
}

and

object CoPersist {
  implicit val coPersistFunctor: Functor[CoPersist] = new Functor[CoPersist] {
    override def map[A, B](fa: CoPersist[A])(f: A => B): CoPersist[B] = CoPersist(fa.run andThen f)
  }
}

and everything should compile.

The thing is the order of implicits. Move object functors to the beginning and everything should compile.

0
On

For using cats functors in your code, you need to try to add settings in your build.sbt file.

scalacOptions += "-Ypartial-unification"

Maybe ths will hepls you. This is limitation of scala compiler https://issues.scala-lang.org/browse/SI-2712