Search code examples
scalafunctional-programmingscala-catshigher-kinded-typeskind-projector

Declare natural transform for batching with kind-projector


I have the following trait:

trait Test[F[_]]{
  def foo: F[Int]
}

And I tried to apply the so-called batching transformation to it as follows:

def withBatching[F[_]](t: Test[F], nat: F ~> F[List[*]]): Test[F[List[*]]] = ???

The problem is it does not compile with the following error:

[error] /Hello.scala:15:66: F[[α$1$]List[α$1$]] takes no type parameters, expected: 1
[error]   def withBatching[F[_]](t: Test[F], nat: F ~> F[List[*]]): Test[F[List[*]]] = ???
[error]                                                                  ^
[error] /Hello.scala:15:48: F[[α$0$]List[α$0$]] takes no type parameters, expected: 1
[error]   def withBatching[F[_]](t: Test[F], nat: F ~> F[List[*]]): Test[F[List[*]]] = ???

Is there a way to declare somethign like F[List[*]] with kind projector?

UPD: I found some workaround with type aliasing type ListT[F[_], A] = F[List[A]] which seems to work, but is there more natural way to do so?


Solution

  • * always binds at the tightest level, which is not what you need for nat and the return type. You should use Lambda syntax provided by kind-projector to explicitly choose the level:

      def withBatching[F[_]](
          t: Test[F], nat: F ~> Lambda[A => F[List[A]]]
      ): Test[Lambda[A => F[List[A]]]] = ???