4 ms·
Other "every day" monoids: - (Array, concat, []) - (Floating point numbers, min, +Infinity) - (Floating point numbers, max, -Infinity) - (Boole
by jfarmer 12y ago
Other "every day" monoids:
- (Array, concat, [])
- (Floating point numbers, min, +Infinity)
- (Floating point numbers, max, -Infinity)
- (Boolean, AND, true)
- (Boolean, OR, false)
- (Subsets of set S, union, {})
- (Subsets of set S, intersection, S)
- (Functions of type S → S, composition, the identity function)
You'll often see folks writing functions from Strings to Strings but returning _null_ or the like in the "empty" case instead of an empty String. Having them instead return the "identity" element of the relevant monoid will always result in a simpler, more composable interface.
- rahimnathwani 12y ago> Having them instead return the "identity" element of the relevant monoid will always result in a simpler, more composable interface. But there may be more than one relevant monoid, and thereby more than one identity element. In the case of a function which returns an integer, should I return the multiplicative identity, or the additive one?
- jfarmer 12y agoFor a given problem, there's often some natural monoidal structure underneath the hood even if the operations aren't explicitly part of the type signature. For example, it's "natural" for the sum of an empty list to be 0 but the product of an empty list to be 1. Why? So that the "hidden homomorphism" is preserved (here ++ is list concatenation): sum(listA ++ listB) == sum(listA) + list(listB) product(listA ++ listB) == product(listA) * product(listB) For similar reasons, given some predicate P is some predicate, the any? should return false for an empty list and all? should return true so that the following hold: all?(P, listA ++ listB) == all?(P, listA) && all?(P, listB) any?(P, listA ++ listB) == any?(P, listA) || any?(P, listB) Behind it all we're not only transforming values of TypeA into values of TypeB , we're doing it in a way that respects some underlying monoidal structure. If you want to think of it in a more programmer-centric way, any time you have an operation that could be as a fold[1] there is an underlying monoidal structure. Monoids permit folding, folding implies the existence of some monoid. [1]: http://en.wikipedia.org/wiki/Fold_(higher-order_function) http://en.wikipedia.org/wiki/Fold_(higher-order_function)