Seguimos con monoides en cats.
Recordemos :
• un Semigrupo representa una operación de suma o combinación;
• un monoide extiende un semigrupo agregando una identidad o un elemento "cero".
Podemos usar semigrupos y monoides importando tres cosas: las type class en sí, las instancias de los tipos que nos interesan y la sintaxis de semigrupo para darnos el operador |+| :
import cats.Monoid
import cats.instances.string._ // for Monoid
import cats.syntax.semigroup._ // for |+|
"Scala" |+| " with " |+| "Cats"
// res0: String = "Scala with Cats"
Con las instancias correctas en el alcance, podemos comenzar a agregar lo que queramos:
import cats.instances.int._ // for Monoid
import cats.instances.option._ // for Monoid
Option(1) |+| Option(2)
// res1: Option[Int] = Some(3)
import cats.instances.map._ // for Monoid
val map1 = Map("a" -> 1, "b" -> 2)
val map2 = Map("b" -> 3, "d" -> 4)
map1 |+| map2
// res2: Map[String, Int] = Map("b" -> 5, "d" -> 4, "a" -> 1)
import cats.instances.tuple._ // for Monoid
val tuple1 = ("hello", 123)
val tuple2 = ("world", 321)
tuple1 |+| tuple2
// res3: (String, Int) = ("helloworld", 444)
También podemos escribir código genérico que funcione con cualquier tipo para el que tengamos una instancia de Monoid:
def addAll[A](values: List[A])
(implicit monoid: Monoid[A]): A =
values.foldRight(monoid.empty)(_ |+| _)
addAll(List(1, 2, 3))
// res4: Int = 6
addAll(List(None, Some(1), Some(2)))
// res5: Option[Int] = Some(3)
Los monoides son una gran puerta de entrada a Cats. Son fáciles de entender y fáciles de usar. Sin embargo, son solo la punta del iceberg en términos de las abstracciones que Cats nos permite hacer.