I want to create a FunctionK
instance with anonymous function. Here is the minimal example of that:
import cats.~>
given (Option ~> List) = {
case Some(a) => a :: Nil
case None => Nil
}
However, this snippet throws compile error:
Missing parameter type
I could not infer the type of the parameter x$1
in expanded function:
x$1 =>
x$1 match
{
case Some(a) =>
a :: Nil
case None =>
Nil
}
Expected type for the whole anonymous function:
cats.arrow.FunctionK[Option, List]
Is the compiler not smart enough to infer all the types, or am I using anonymous function not the right way?
Compiled with Scala==3.4.0-RC1
and cats.core==2.10.0
Let's analyze it step by step.
FunctionK
is actually not a function. In Scala 3-only world it could be defined as:
type FunctionK[F[_], G[_]] = [A] => F[A] => G[A]
which would make it a polymorphic function type. But it was defined before Scala 3 became a thing and needs to be backward compatible with the old representation, that it:
trait FunctionK[F[_], G[_]] {
def apply[A](fa: F[A]): G[A]
}
which was a Scala 2's workaround for not having polymorphic function types.
In situations like:
trait FunctionLike[A, B] {
def method(a: A): B
}
val fl: FunctionLike[Int, String] = _.toString
we are using Single Abstract Method syntax - compiler sees that we are using lambda syntax for something where we could be using new FunctionLike[Int, String] { ... }
but it also sees that this trait
/abstract class
has only 1 abstract method so it can assume that we want to implement the whole trait
/abstract class
by implementing this method (and so we can pretend that it's a function).
Thing is, SAM seems to be currently implemented only for normal (monomorphic) methods, and when you are using lambdas for polymorphic ones, it will not make the connection:
import cats.~>
given (Option ~> List) = [A] => (opt: Option[A]) => opt match {
case Some(a) => a :: Nil
case None => Nil
}
// error:
// Found: [A] => (opt: Option[A]) => List[A]
// Required: cats.arrow.FunctionK[Option, List]
In your case, you additionally used syntax for monomorphic function type: currently when you need a polymorphic function type you have to write: [A] => (a: A) => ...
- type parameters have to be explicitly defined and explicitly used in one of the arguments.
Gaël's answers explains how you can actually implements it.