Code
scala
// Define
trait Semigroup[A] {
def combine(x: A, y: A): A
}
// Instances
implicit val intSum: Semigroup[Int] = (x, y) => x + y
implicit val strConcat: Semigroup[String] = (x, y) => x + y
// Generic function
def combineAll[A](xs: List[A])(implicit s: Semigroup[A]): A =
xs.reduce(s.combine)
combineAll(List(1, 2, 3)) // 6
combineAll(List("a", "b", "c")) // "abc"
// Cats provides Monoid, Functor, Monad, etc. the same way