Please Depend on Semigroups
Posted on October 25, 2017An Abridged History of Semigroup in Haskell
Monoids have been a ubiquitous part of modern functional programming for many years. Recently Semigroups, which are more general but weaker than monoids, have seen a lot of use as well.
At the time Monoid
was added to base, a Semigroup
class was not added alongside it. In hindsight, we would have liked a Semigroup
class as a superclass of Monoid
. Every Monoid is a Semigroup, and there are lots of useful structures that are only semigroups, like NonEmpty
lists. NonEmpty Lists lack the empty list, which is the identity of the append operation. Other useful structures come about that are related to Semigroup but don’t need a full Monoid, such as Validation
and Foldable1
. Hence Edward Kmett wrote a library called semigroups. The package provides the Semigroup
class and NonEmpty
lists. Due to the usefulness of the abstraction, and the fact that many of Edward’s other packages depend on it, the semigroups package is very widely used.
Later, Semigroup
and NonEmpty
were added to base
in version 4.91, meaning that anyone using GHC 8.0 or higher would get them for free, without any external dependencies.
Why your library should still depend on semigroups
Now that base has semigroups, it is tempting to remove our dependencies on the semigroups package and deprecate it out of existence. But there is a good reason to still depend on it: supporting older GHCs.
If you use the Semigroup
typeclass without depending on the semigroups package, your code will only run on GHC >= 8.0. But at the time of writing, several popular operating systems are still shipping GHC 7.10, and there are probably plenty of people stuck on older versions for their particular project or team. Adding a semigroups dependency helps the community, because it can make the difference between your library being usable for someone or unusable.
But looking at the module names in the semigroups package, it would seem they will clash with the modules recently added to base! Thankfully this is not the case, because semigroups is smart enough to “turn itself off” with CPP when it detects a new enough base version.
In summary, please depend on semigroups if you depend on Semigroup
:)
In order to preserve backward compatibility,
Semigroup
is not currently a superclass ofMonoid
, but in a later version it will be.↩︎
We’re using functional programming to set up the infrastructure that we use from day to day.
> George Wilson
George Wilson is an enthusiastic programmer at the Queensland Functional Programming Lab. George enjoys writing code, and speaking and writing about Haskell and functional programming.