0

I'm not looking for the mathematical definition of a monoid, I'm looking for why monoid are important in haskell. (I'm not talking about Monoid class, just I'm talking about monoid structure)

Is it correct to describe the following as one of the characteristics of a monoid? "A monoid can see its elements all in the same shape" For example, the monoid of natural numbers,+, including 0, allows all its members to be viewed in the shape _ + _. I'm assuming that associativity law is used to modularize expressions that can be viewed as such.

  • The important thing is not that every element can be decomposed into `_ + _` (which may only be true for the trivial decomposition `e + x == x`, where `e` is the identity), but that `x + y` is also an element of the monoid for all `x` and `y` in the monoid. – chepner Feb 24 '23 at 14:13
  • I thought about why monoid with "identity" rather than subgroup would be treated differently, and what happens when a (Natural, +) monoid contains a zero. – Lionhairdino L. Feb 24 '23 at 14:22
  • I don't follow. The identity element is the defining feature that separates a monoid from a semigroup, and 0 *is* the identity element for the (Natural, +) monoid. – chepner Feb 24 '23 at 14:33
  • Sorry for the misrepresentation. "What happens when a (Natural, +) structure contains a zero." – Lionhairdino L. Feb 24 '23 at 14:39
  • 1
    You might like [this blog post](https://izbicki.me/blog/gausian-distributions-are-monoids.html) which describes how monoidal structure/laws give rise to an algorithm multiple orders of magnitudes faster than the unstructured analog (for cross validation in data modeling) and that supports automatic parallelization. – Daniel Wagner Feb 24 '23 at 21:25
  • 1
    What I think you're describing is true for all abstractions. For example the number structure allows `_ + _` and `_ - _` and `_ * _` and so on. The monoid structure does this, because it's an abstraction too, but it's not `_ + _`, rather it's `_ _ _` as the thing in the middle is specific to each monad, and some extra rules, like `_ _ 0 == _`. – user253751 Feb 25 '23 at 05:38

1 Answers1

2

If you're asking whether an element x of a monoid M can always be written in the form _ + _, then this is trivially true because x ≡ x <> mempty holds always, it's right there in the monoid laws. But that's not very enlightening.

I suppose what you meant was, every element n ∈ ℕ can be written in the form

     ... + 1 + 1 + 1 + ...

Even that isn't completely true, because what about 0? But of course we do also have 0, it's literally just mempty.

Monoids with such a property are the free monoids. In Haskell, free monoids are usually identified with lists, which may be surprising because I just said the natural numbers are a free monoid. The key is, this sort of thing generally holds up to isomorphism. The natural numbers are isomorphic to the Haskell type [()], e.g. 4 is represented by [(),(),(),()]. For lists of other types the freeness is witnessed by e.g.

   "Hello, World" ≡ "H"<>"e"<>"l"<>"l"<>"o"<>","<>" "<>"W"<>"o"<>"r"<>"l"<>"d"

Specifically, for a free monoid this decomposition is unambiguous.

But are all monoids free? No. For a counterexample, you need to go no further than the integers with addition. Naïvely one might think that this is a free monoid with the generators 1 and -1, but it's not – for example, the number 2 could be written both as 1 + 1 and as 1 + (-1) + 1 + 1, etc..
(The integers are however a free group.)

In practice, for many monoids, even when they could be considered as free monoids, this is not necessarily a useful perspective. For lists, it's clear that we're talking free over the set specified by the type of list, but in other cases it's not. For example, Maybe (Char, String) is isomorphic to String and thus also a free monoid, but when using that type you would probably want to express something different.

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • Thank you for the very meaningful response, even though it didn't answer all of my questions. Let's say we create a new type `Add` for `+`, and let the functor do the actual Adding later. To express any number as an `Add`, `Add` needs to take an `Add` as an argument. If we express `(1+2)+3`, we get `Add (Add 1 2) 3`, which is out of type. We need to be able to write `Add (Add 1 2) (Add 3 0)`, and this is where the concept of a monoid with Identity comes in. I apologize for the ambiguity, and I'll re-post my question with more clarity. Thanks again for your response. – Lionhairdino L. Feb 25 '23 at 07:14
  • @LionhairdinoL. We absolutely do not have to be able to write `Add (Add 1 2) (Add 3 0)` to capture the expression `(1+2)+3`. Not sure where you get that idea. – Daniel Wagner Feb 26 '23 at 18:02
  • What definition of `Add` do you have in mind that `Add (Add 1 2) 3` is "out of type", but `Add 1 2` is not? – chepner Feb 27 '23 at 13:55