[Functional Programming] foldMap for Monoids

Let's say we have following semigroups:

// Total: Sum up all the number
const Total = (x) => ({
  x,
  concat(o) {
    return Total(o.x + x);
  },
  fold() {
    return x;
  },
  toString() {
    return `Total(${x})`;
  },
});
Total.empty = () => Total(0);

const Max = (x) => ({
  x,
  concat(o) {
    return Max(Math.max(x, o.x));
  },
  fold() {
    return x;
  },
});
Max.empty = () => Max(Number.MIN_VALUE);

We want to define a 'List' type which has 'foldMap' function:

const List = (x) => ({
  x,
  foldMap(type, _empty) {
    const empty = _empty ? _empty : type.empty();
    if (!empty) throw new Error(`foldMap expect an empty as second value`);
    return x
      .map(type)
      .reduce((acc, curr) => {
        return acc.concat(curr);
      }, empty)
      .fold();
  },
});

Then we can use it:

console.log(List([1, 2, 3]).foldMap(Total)); // 6
console.log(List([1, 2, 3]).foldMap(Total, Total.empty()));
console.log(List([1, 2, 3]).foldMap(Max));  // 3
console.log(List([1, 2, 3]).foldMap(Max, Max.empty()));
原文地址:https://www.cnblogs.com/Answer1215/p/12980772.html