// @flow import type { Semigroup } from './Semigroup' import { getProductSemigroup } from './Semigroup' export interface Monoid extends Semigroup { empty(): A } // Fold a list using the monoid export function concatAll(monoid: Monoid, as: Array): A { return as.reduce(monoid.concat, monoid.empty()) } export function getProductMonoid(amonoid: Monoid, bmonoid: Monoid): Monoid<[A, B]> { return { empty: () => [amonoid.empty(), bmonoid.empty()], concat: getProductSemigroup(amonoid, bmonoid).concat } } export function getDualMonoid(monoid: Monoid): Monoid { return { empty: monoid.empty, concat: (x, y) => monoid.concat(y, x) } } // Boolean monoid under conjunction export const all: Monoid = { empty: () => true, concat: (x, y) => x && y } // Boolean monoid under disjunction export const any: Monoid = { empty: () => false, concat: (x, y) => x || y } // Monoid under addition export const sum: Monoid = { empty: () => 0, concat: (x, y) => x + y } // Monoid under multiplication export const product: Monoid = { empty: () => 1, concat: (x, y) => x * y } export const stringMonoid: Monoid = { empty: () => '', concat: (x, y) => x + y } export const arrayMonoid: Monoid> = { empty: () => [], concat: (x, y) => x.concat(y) }