Entre otros tipos, Cats proporciona una instancia de Invariant para Monoid.
Imagina que queremos producir un monoide para el tipo símbolo de Scala. Cats no proporciona un Monoide para Símbolo, pero sí proporciona un Monoide para un tipo similar: Cadena o String. Podemos escribir nuestro nuevo semigrupo con un método vacío que se basa en la cadena vacía y un método de combinación que funciona de la siguiente manera:
- aceptar dos Símbolos como parámetros;
- convertir los Símbolos a Cadenas;
- combine las cadenas usando Monoid[String];
- convertir el resultado de nuevo en un Símbolo.
Podemos implementar combine usando imap, pasando funciones de tipo String =>Symbol y Symbol => String como parámetros. Aquí está el código, escrito usando el método de extensión imap proporcionado por cats.syntax.invariant:
import cats.Monoid
import cats.instances.string._ // for Monoid
import cats.syntax.invariant._ // for imap
import cats.syntax.semigroup._ // for |+|
implicit val symbolMonoid: Monoid[Symbol] = Monoid[String].imap(Symbol.apply)(_.name)
Monoid[Symbol].empty
// res3: Symbol = '
Symbol("a") |+| Symbol("few") |+| Symbol("words")
// res4: Symbol = 'afewwords