I'm going through "Scala with cats". In 3.5.2 (p. 58, bottom) there is an example:
def doMath[F[_]](start: F[Int])(implicit functor: Functor[F]): F[Int] =
start.map(n => n + 1 * 2)
And the usage is pretty straightforward:
import cats.instances.option._ // for Functor
import cats.instances.list._
// for Functor
doMath(Option(20))
// res3: Option[Int] = Some(22)
doMath(List(1, 2, 3))
// res4: List[Int] = List(3, 4, 5)
How should I understand the type constructor in the method signature (F[_])? A couple of pages earlier it was said, that the type parameter should be provided to create a type. Here the whole thing (F[_]) is a type parameter and it looks, that _ is a wildcard, so that the compiler can infer the type parameter of F.
The type constructor
F[_]is required to be a member of theFunctortypeclass. This constraint is put onFby the implicit parameter listThe whole signature
might be interpreted as follows
where I use the phrase effectful value to emphasise that it is not a value of raw type such as
Intbut instead a value of type constructed after applying type constructorFto type argumentInt, namelyF[Int].Furthermore I use the phrase member of in the sense of
Note the usage of underscore
_in this context is not related to inference. TheF[X]andF[_]type constructor notations mean exactly the same thing. The type argumentXis not used anywhere in the rest of the method signature, and for that reason by convention we use the underscore syntaxF[_]. Another convention is to use lower-casexinF[x], as opposed toF[X], to emphasisexis not used.Indeed
F[_]is a type parameter in its own right and when type constructorFunctoris applied to it we get proper typeFunctor[F]even though bothFandFunctorare type constructors, for example