We often need to aggregate data. Hadoop/Spark map-reduce is a classic example of this (the reduce part). There are other more trivial examples - e.g. summing the line items in a shopping basket to calculate the total basket price Semigroups allow us to parallelize operations on large and small data sets, then combine the results together. In essence Semigroup encapsulates the reduce part of map reduce. You can find complete examples of the concepts discussed on my blog in my Github repo .
We often need to combine data types that may be “empty” e.g. empty Lists or Options. How do we combine a List[Int] to produce an Int if the List is empty? What is the result? How about List[String] => String. Logically we would expect zero for the Int example and "" for the String but how do we represent this? The simple Monoid extends Semigroup and adds a default or fallback value for the given type.
Type classes are everywhere in the Scala ecosystem. If you want to learn advanced libraries like Scalaz, Cats or Shapeless you need to know about them. Even if you don’t plan to use these libraries you can (and probably should) use type classes in your own applications. Type classes are borrowed from Haskell and are sometimes called “ad-hoc polymorphism”. If you want to know what that means read on Type classes are like the adapter pattern on steroids.