|
Any++
|
The Monoid is a simple algebraic structure that consists of a set of elements, an associative binary operation, and an identity element.
It is a fundamental concept in abstract algebra and has many applications in computer science, especially in functional programming.
If you have ever heard of the term "type class", you have probably heard of the Monoid as well and you may skip this section.
But if you are new to the concept of type classes, the Monoid is a great example to start with, because it is simple and easy to understand and because it is inherrent self refernetial, it shows the obstacles an implementation of type has to overcome.
Lets start with a colloquial definition of the Monoid: When a type wants to be a Monoid,
The Hskell definition of the Monoid type class looks like this:
We can see that the Monoid type class inherits from the Semigroup type class, which is a type class that only requires the binary operation. This is for our discussion here not relevant, but it is a common pattern in Haskell to have a hierarchy of type classes, where each type class inherits from one or more other type classes. mempty is the identity element, mappend is the binary operation, and mconcat is the concatenation operation. mapapend requires the binary operation. mempty and mconcat have default implementations, witch reference each other. mconcat is defined in terms of mappend and mempty, and mempty is defined as the result of concatenating an empty list. For example, if a type provides an implementation for mappend and mempty, then it can use the default implementation for mconcat, which is defined in terms of mappend and mempty. This is a powerful feature of type classes, because it allows to define a lot of functionality for a type class, wher a concrete type only has to provide a few implementations to get all the other functionality for free.
In Rust , the Monoid trait looks like this:
See a complete example on Compiler Explorer We can see that the Monoid trait with it's three requirements, which are the same as the Haskell type class. The identity element is provided by the empty() function, the binary operation is provided by the append() function, and the concatenation operation is provided by the concat() function, which has a default implementation that relies on the empty() function as the starting point for the fold. ''IntoIterator'' is a trait that allows to convert a type into an iterator, which is a type that can be used to iterate over a sequence of values. In the case of an self referential type class like the Monoid, you can not use this trait as a type, because it is not object safe.
How far can we get there with standrd C++23?
Gracyfully to Steve Downey, we can get pretty far, let's see his approach to C++0x Concepts with Concept Maps using C++23 Library Tech in the next chapter.