4 ms·
it's not exactly order independence, it's associativity: (a • b) • c == a • (b • c) i.e. "no matter where you put the parentheses, it'll give the same res
by uryga 7y ago
it's not exactly order independence, it's associativity:
(a • b) • c == a • (b • c)
i.e. "no matter where you put the parentheses, it'll give the same result". this DOESN'T mean that
a • b == b • a
though it may be true for some monoids like addition/multiplication over numbers¹.
you'll notice that associativity indeed holds for strings (or arrays of some T), where concatenation is the monoidal operation:
("he" ++ "ll") ++ "o!" ==
"he ++ ("ll" ++ "o!") ==
"hello!"
though at first blush associativity may not seem very useful, it is! it means folding/"summing" a sequence of monoidal values is trivially parallelizable. i.e. if you've got a sequence
as = [a0, a1, a2, ..., an-1, an]
and you want to "sum"/fold it using a's monoidal operation "•":
r = (a0 • a1 • a2 • ... • an)
you can split it into chunks across multiple workers and then "sum" the results of summing each chunk:
r0 = (a0•a1•a2) // worker 0
r1 = (a3•a4•a5) // worker 1
...
rm = (an-2,an-1,an) // worker m
r = r0•r1•...•rm // sum up what the workers produced
the nice thing is, as long as we don't reorder the elements, we'll always get the same result no matter how we chunk up `as`! and this will hold for any monoid `(a, •)`.
btw, an example of a less trivial monoid is `sorted lists of T `:
- `•`, the monoidal operation, is `merge(a, b)`, which combines two sorted lists into a new sorted list: `merge([1,2,3,5], [2,4]) == [1,2,2,3,4,5]`
- `e`, the "neutral element", is just the empty list `[]`
this is a (commutative) monoid, and you could say that mergesort relies on its monoidal properties to work!
---
¹ if you can swap values around and still get the same result, you've got a "commutative monoid".
- uryga 7y agowhoops, that last code block was supposed to have rm = (an-2•an-1•an) instead of the commas.