I was going through "Scala with Cats" by Underscore and stumbled upon the following statement:
Cats provides a
cats.syntax.apply
module that makes use ofSemigroupal
andFunctor
to allow users to sequence functions with multiple arguments.
As far as I understand we can only sequence functions with single arguments because functions can return only single value.
import cats.implicits._
val f1: Int => Int = x => x + 1
val f2: Int => Int = x => x * 4
val f3: Int => String = x => s"x = $x"
f1.map(f2).map(f3)(5)
For the following example, it says: Internally mapN
uses the Semigroupal
to extract the values from the Option
and the Functor
to apply the values to the function.
final case class Cat(name: String, born: Int, color: String)
(
Option("Garfield"),
Option(1978),
Option("Orange & black")
).mapN(Cat.apply)
// res10: Option[Cat] = Some(Cat("Garfield", 1978, "Orange & black"))
Here Cat.apply
is indeed a function with multiple arguments but it is chained to a function that itself returns a tuple of options i.e., a single value. We could probably make it accept multiple arguments like so:
final case class Cat(name: String, born: Int, color: String)
val f: (String, Int, String) => (Option[String], Option[Int], Option[String]) =
(name, year, color) => (Option(name), Option(year), Option(color))
f("Garfield", 1978, "Orange & black").mapN(Cat.apply)
Now we have functions f
and Cat.apply
that accept multiple arguments and are chained together. Is it what the above statement was pointing to? But then I can't seem to find a way to chain more functions further. Is the statement applicable to chaining multiple argument functions only at one level? Also, notice here that function f
is applied eagerly in contrast to the single argument function chaining example depicted above. Is is possible to apply functions lazily here?
There isn't much explanation I could find anywhere on Semigroupal on internet. Could anyone please explain this statement with an example? TIA.