4 ms·
For 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
by jfarmer 12y ago
For 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)