// @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)
}