Monoid
API Documentation: Monoid
Monoid extends the power of Semigroup by providing an additional empty value.
trait Semigroup[A] {
  def combine(x: A, y: A): A
}
trait Monoid[A] extends Semigroup[A] {
  def empty: A
}
        This empty value should be an identity for the combine operation, which means the following equalities hold
        for any choice of x.
combine(x, empty) = combine(empty, x) = x
        Many types that form a Semigroup also form a Monoid, such as Ints (with 0) and Strings (with "").
import cats.Monoid
implicit val intAdditionMonoid: Monoid[Int] = new Monoid[Int] {
  def empty: Int = 0
  def combine(x: Int, y: Int): Int = x + y
}
val x = 1
        Monoid[Int].combine(x, Monoid[Int].empty)
// res1: Int = 1
Monoid[Int].combine(Monoid[Int].empty, x)
// res2: Int = 1
        
        Example usage: Collapsing a list
In the Semigroup section we had trouble writing a generic combineAll function because we had nothing
        to give if the list was empty. With Monoid we can return empty, giving us
def combineAll[A: Monoid](as: List[A]): A =
  as.foldLeft(Monoid[A].empty)(Monoid[A].combine)
        which can be used for any type that has a Monoid instance.
import cats.syntax.all._
        combineAll(List(1, 2, 3))
// res3: Int = 6
combineAll(List("hello", " ", "world"))
// res4: String = "hello world"
combineAll(List(Map('a' -> 1), Map('a' -> 2, 'b' -> 3), Map('b' -> 4, 'c' -> 5)))
// res5: Map[Char, Int] = Map('b' -> 7, 'c' -> 5, 'a' -> 3)
combineAll(List(Set(1, 2), Set(2, 3, 4, 5)))
// res6: Set[Int] = HashSet(5, 1, 2, 3, 4)
        This function is provided in Cats as Monoid.combineAll.
The Option monoid
        There are some types that can form a Semigroup but not a Monoid. For example, the
        following NonEmptyList type forms a semigroup through ++, but has no corresponding
        identity element to form a monoid.
import cats.Semigroup
final case class NonEmptyList[A](head: A, tail: List[A]) {
  def ++(other: NonEmptyList[A]): NonEmptyList[A] = NonEmptyList(head, tail ++ other.toList)
  def toList: List[A] = head :: tail
}
object NonEmptyList {
  implicit def nonEmptyListSemigroup[A]: Semigroup[NonEmptyList[A]] = _ ++ _
}
        How then can we collapse a List[NonEmptyList[A]] ? For such types that only have a Semigroup we can
        lift into Option to get a Monoid.
import cats.syntax.all._
implicit def optionMonoid[A: Semigroup]: Monoid[Option[A]] = new Monoid[Option[A]] {
  def empty: Option[A] = None
  def combine(x: Option[A], y: Option[A]): Option[A] =
    x match {
      case None => y
      case Some(xv) =>
        y match {
          case None => x
          case Some(yv) => Some(xv |+| yv)
        }
    }
}
        This is the Monoid for Option: for any Semigroup[A], there is a Monoid[Option[A]].
Thus:
import cats.Monoid
import cats.data.NonEmptyList
import cats.syntax.all._
val list = List(NonEmptyList(1, List(2, 3)), NonEmptyList(4, List(5, 6)))
val lifted = list.map(nel => Option(nel))
        Monoid.combineAll(lifted)
// res8: Option[NonEmptyList[Int]] = Some(
//   value = NonEmptyList(head = 1, tail = List(2, 3, 4, 5, 6))
// )
        This lifting and combining of Semigroups into Option is provided by Cats as Semigroup.combineAllOption.
N.B.
        Cats defines  the Monoid type class in cats-kernel. The
        cats package object
        defines type aliases to the Monoid from cats-kernel, so that you can simply import cats.Monoid.