DEV Community

Discussion on: Explain what a monoid is Like I'm Five

Collapse
 
idanarye profile image
Idan Arye

I'll do you one better - why is a monoid?

Others have explained the mathematical concept, and math is cool and all - but adding numbers and concatenating strings are not unique to functional programming - you need to do this stuff in procedural programming too. So why does the functional programming literature need to specifically discuss the nature of monoids?

Because of actions.

In procedural programming, actions are easy - all your statements are actions. You run a statement to perform an action, whether that action is to set a variable, print something to a file, send an HTTP request or whatever. Expressions are just there to help you set the parameters of your actions.

Functional programming, on the other hand, are about expressions. A functional program, rather then being a long sequence of actions, is composed of a big, compound expression to be resolved. There are no statements - doing actions for the sake of their side-effects is considered impure.

So, in functional programming you will replace actions like variable settings and looping with clever structuring of function calls. But what about the cases where you have to do an action for it's side-effects - like writing to a file? Even in pure functional languages like Haskell you need to be able to do those!

The solution is to have values that represent actions. These values can be created in the functional code, and then be passed to a special component that can run impure code. That way you can do side-effects while maintaining functional purity.

In order to do that - actions are being treated at monoids under the operation of composition! To understand how that operation works we'll have to discuss monads, but for now let's just say that A + B means "Do A and then do B".

So how are actions monoids? Let us examine the definition:

  1. Are they closed under the binary operation? Yes - if I compose two actions, I get a new action ("do them both!").

  2. Are they associative? Yes - (A + B) + C is the same as A + (B + C), because they both do A, B, and C in that order.

  3. And what about the identity? The identity is NOP - do nothing. A + NOP means "do A then do nothing" which is the same as just "do A". Same for NOP + A.

So now that actions are monoids, your functional code can mix and match them to create the sequence of side-effects you want to run. This is still purely functional because you are not running anything yet - you are merely composing a big action to send to the executor to run.