Home > Software engineering >  Haskell, implementing Monoids. What is Semigroup and why does it act so weird?
Haskell, implementing Monoids. What is Semigroup and why does it act so weird?

Time:07-26

I wanted to implement a Custom Datatype named ComplexNumber like this: data ComplexNumber a = C (a,a)

Now I wanted to implement the Monoid Variable and define the binary mempty Element and the mappend like this:

instance Num a => Monoid (ComplexNumber a) where
    mempty = C (0,0)
    mappend = (C (a1, b1)) (C (a2, b2)) = C (a1   a2, b1   b2)

but this didn't work out, so tried to figure out why and came across Semigroup (which I still dont really understand) and came to a soloution that atleast compiles and seems to work with this:

instance Num a => Semigroup (ComplexNumber a) where
    (C (a1, b1)) <> (C (a2,b2)) = C (a1   a2, b1   b2)

instance Num a => Monoid (ComplexNumber a) where
    mempty = C (0,0)

The funny thing is, when i remove the implementation of Semigroup the programm doesn't compile anymore and gives me following error:

    * Could not deduce (Semigroup (ComplexNumber a))
        arising from the superclasses of an instance declaration
      from the context: Num a
        bound by the instance declaration at Aufgabe_10.hs:9:10-42
    * In the instance declaration for `Monoid (ComplexNumber a)'
  |
9 | instance Num a => Monoid (ComplexNumber a) where
  |  

Why is that i can compile those two sections together, but when i remove the semigroup an error occurs ? And what in particular is this Semigroup thing

CodePudding user response:

Semigroup is just the class of all types that have an implementation of the <> operation, in a way so that it's associative (i.e. that a<>(b<>c) ≡ (a<>b)<>c, which does hold true for your complex numbers if we disregard small floating-point deviations).

Monoid is the class of of semigroups which additionally have a neutral element mempty, i.e. an element that always fulfills mempty <> a ≡ a <> mempty ≡ a (also true for complex numbers with addition and zero).
This would be a nonsensical requirement for a type that doesn't even have the <> operation, i.e. that doesn't have a Semigroup instance. This is expressed by Semigroup being a superclass of Monoid, and thus it's impossible to have a type which is an instance of Monoid but not of Semigroup.

Historically, Semigroup and Monoid were separate classes, with the older Monoid shipping its own mappend operation that is the equivalent to the modern <>. Some older books / tutorials are still based on this old class hierarchy.
But because there are a bunch of types that are only semigroups, but not monoids, the class hierarchy was changed.

CodePudding user response:

A monoid [wiki] is a semigroup [wiki] with identity: it has an identity element e [wiki] for which the associative binary operation will x ⊕ e = e ⊕ x = x for all elements x in the set. Every monoid is thus a semigroup, since a semigroup is an algebraic structure with an associative binary operator for which the same properties thus hold as in a monoid, except that there is no need for an identity element e.

Since base-4.9.0.0, a Semigroup class has been introduced, but then Semigroup and Monoid did not "live together". Since it does not make much sense to define a different binary operator for the Semigroup than for the Monoid instance (since that would likely introduce confusion), since base-4.11.0.0, Semigroup is a superclass of Monoid. Indeed, Monoid is defined as [src]:

class Semigroup a => Monoid a where
    # …

This means that in order to make something an instance of Monoid, it has to be an instance of Semigroup as well. The mappend :: Monoid a => a -> a -> a will automatically link to the implementation of (<>) :: Semigroup a => a -> a -> a and will, likely, eventually be removed.

You thus can no longer define an instance of Monoid without defining an instance of Semigroup. But you can "mechanically" create an instance from an old instance of Monoid, since you simply move the implementation of mappend from the Monoid instance to the instance for Semigroup.

  • Related