Skip to content

Summon FunctionK for CopK do not work for path dependent type #279

Open
@mleclercq

Description

@mleclercq

Considering the following example where

  • FooOp[A] is defined inside a trait which has a T type parameter
  • BarOp[A] is defined simply at the top-level
import cats.~>
import iota.TListK.:::
import iota.{CopK, TNilK}

trait Foo[T] {
  case class FooOp[A](t: T)
}

case class BarOp[A](s: String)

In the context where T is still generic, I can define the coproduct of FooOp and BarOp as follow:

trait FooBar[T] extends Foo[T] {
  type FooBarOp[A] = CopK[FooOp ::: BarOp ::: TNilK, A]
}

Now fixing T to something specific, I can define two FunctionK on both FooOp and BarOp

object FooBarInt extends FooBar[Int]
import FooBarInt._

implicit val FooToOpt: FooOp ~> Option = new (FooOp ~> Option) {
  def apply[A](fa: FooOp[A]): Option[A] = None
}
implicit val BarToOpt: BarOp ~> Option = new (BarOp ~> Option) {
  def apply[A](fa: BarOp[A]): Option[A] = None
}

But the FunctionK on the coproduct cannot be summoned

val FooBarToOpt = CopK.FunctionK.summon[FooBarOp, Option]
[error]   could not find implicit value for parameter e: cats.arrow.FunctionK[FooBar.this.FooOp,Option]
[error]   val FooBarToOpt = CopK.FunctionK.summon[FooBarOp, Option]
[error]                                          ^

Using CopK.FunctionK.of does not work either

val FooBarToOpt = CopK.FunctionK.of[FooBarOp, Option](FooToOpt, BarToOpt)
[error]   Missing interpreter FunctionK[FooBar.this.FooOp, Option]
[error]   val FooBarToOpt2 = CopK.FunctionK.of[FooBarOp, Option](FooToOpt, BarToOpt)
[error]                                                         ^

Note that the FunctionK can be implemented by hand so it is legitimate to try to have it implicitly

val manualFooBarToOpt: FooBarOp ~> Option = new (FooBarOp ~> Option) {
  val InjFoo = CopK.Inject[FooOp, FooBarOp]
  val InjBar = CopK.Inject[BarOp, FooBarOp]
  def apply[A](fa: FooBarOp[A]): Option[A] = fa match {
    case InjFoo(foo) => FooToOpt(foo)
    case InjBar(bar) => BarToOpt(bar)
  }
}

The example above has been tested with scala 2.12.8

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions