Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
mleclercq opened this issue Mar 2, 2019 · 0 comments
Open

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

mleclercq opened this issue Mar 2, 2019 · 0 comments

Comments

@mleclercq
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant