A monoid is a semigroup with an identity element. Formally, the identity element z is an element for which an equation, z + x = x + z = x, holds for any x. This equation is called identity property. Both closure and associativity properties that are defined for semigroups are also required to hold for a monoid.
The existence of the identity property requires us to implement the monoid, as follows:
trait Monoid[S] extends Semigroup[S] {
def identity: S
}
The check we specified for the semigroup also needs to be augmented for the monoid to verify that the new property holds:
def identity[S : Monoid : Arbitrary]: Prop =
forAll((a: S) => {
val m = implicitly[Monoid[S]]
m.op(a, m.identity) == a && m.op(m.identity, a) == a
})
def monoidProp[S : Monoid : Arbitrary]: Prop = associativity[S] && identity[S]
Now, we can define our first monoid, which will...