Mathematical structures that define operations with specific properties, providing the foundation for generic and composable operations in functional programming.
Associative binary operation - combines two values of the same type.
interface Semigroup<A> {
readonly concat: (x: A, y: A) => A;
}Usage Examples:
import { semigroupSum, semigroupProduct, semigroupString } from "fp-ts/lib/Semigroup";
// Numeric addition
const sum = semigroupSum.concat(5, 10); // 15
// Numeric multiplication
const product = semigroupProduct.concat(3, 4); // 12
// String concatenation
const greeting = semigroupString.concat("Hello", " World"); // "Hello World"
// Custom semigroup for maximum
const semigroupMax: Semigroup<number> = {
concat: (x, y) => Math.max(x, y)
};
const maximum = semigroupMax.concat(3, 7); // 7Semigroup with an identity element (empty/neutral value).
interface Monoid<A> extends Semigroup<A> {
readonly empty: A;
}Built-in Monoids:
/**
* Monoid for number addition (identity: 0)
*/
const monoidSum: Monoid<number>;
/**
* Monoid for number multiplication (identity: 1)
*/
const monoidProduct: Monoid<number>;
/**
* Monoid for string concatenation (identity: "")
*/
const monoidString: Monoid<string>;
/**
* Monoid for boolean AND (identity: true)
*/
const monoidAll: Monoid<boolean>;
/**
* Monoid for boolean OR (identity: false)
*/
const monoidAny: Monoid<boolean>;
/**
* Monoid for void (identity: undefined)
*/
const monoidVoid: Monoid<void>;Usage Examples:
import { monoidSum, monoidString, fold } from "fp-ts/lib/Monoid";
// Identity elements
const zeroSum = monoidSum.empty; // 0
const emptyString = monoidString.empty; // ""
// Fold array with monoid
const numbers = [1, 2, 3, 4, 5];
const total = fold(monoidSum)(numbers); // 15
const words = ["Hello", " ", "World"];
const sentence = fold(monoidString)(words); // "Hello World"
// Empty array folds to identity
const emptySum = fold(monoidSum)([]); // 0Create new monoids from existing ones.
/**
* Dual monoid - reverses the operation order
* @param M - Original monoid
* @returns Monoid with reversed operation
*/
function getDualMonoid<A>(M: Monoid<A>): Monoid<A>;
/**
* Tuple monoid - combines monoids elementwise
* @param MA - Monoid for first element
* @param MB - Monoid for second element
* @returns Monoid for tuples
*/
function getTupleMonoid<A, B>(MA: Monoid<A>, MB: Monoid<B>): Monoid<[A, B]>;
/**
* Record monoid - combines records with monoid per field
* @param monoids - Record of monoids for each field
* @returns Monoid for records
*/
function getStructMonoid<O extends Record<string, any>>(
monoids: { [K in keyof O]: Monoid<O[K]> }
): Monoid<O>;
/**
* Function monoid - combines functions returning monoidal values
* @param M - Monoid for return type
* @returns Monoid for functions
*/
function getFunctionMonoid<M>(M: Monoid<M>): <A>() => Monoid<(a: A) => M>;
/**
* Endomorphism monoid - combines functions from A to A
* @returns Monoid for endomorphisms (function composition)
*/
function getEndomorphismMonoid<A>(): Monoid<Endomorphism<A>>;Usage Examples:
import { getDualMonoid, getTupleMonoid, getStructMonoid } from "fp-ts/lib/Monoid";
import { monoidSum, monoidString } from "fp-ts/lib/Monoid";
// Dual monoid (subtraction instead of addition)
const dualSum = getDualMonoid(monoidSum);
const result1 = dualSum.concat(10, 3); // 3 - 10 = -7
// Tuple monoid
const tupleMonoid = getTupleMonoid(monoidSum, monoidString);
const combined = tupleMonoid.concat([1, "Hello"], [2, " World"]); // [3, "Hello World"]
// Struct monoid
const structMonoid = getStructMonoid({
count: monoidSum,
message: monoidString
});
const merged = structMonoid.concat(
{ count: 1, message: "Hello" },
{ count: 2, message: " World" }
); // { count: 3, message: "Hello World" }Monoid with inverse operation.
interface Group<A> extends Monoid<A> {
readonly inverse: (a: A) => A;
}Structure with two operations: addition and multiplication.
interface Ring<A> extends Semiring<A> {
readonly sub: (x: A, y: A) => A;
}
interface Semiring<A> {
readonly add: (x: A, y: A) => A;
readonly zero: A;
readonly mul: (x: A, y: A) => A;
readonly one: A;
}Built-in Rings:
/**
* Ring for numbers with standard arithmetic
*/
const ringNumber: Ring<number>;Ring with division (multiplicative inverse).
interface Field<A> extends Ring<A> {
readonly degree: (a: A) => number;
readonly div: (x: A, y: A) => A;
readonly mod: (x: A, y: A) => A;
}
/**
* Field for numbers with division
*/
const fieldNumber: Field<number>;Structure with upper and lower bounds.
interface Bounded<A> extends Ord<A> {
readonly top: A;
readonly bottom: A;
}
/**
* Bounded instance for boolean (top: true, bottom: false)
*/
const boundedBoolean: Bounded<boolean>;Structures with join (∨) and meet (∧) operations.
interface JoinSemilattice<A> {
readonly join: (x: A, y: A) => A;
}
interface MeetSemilattice<A> {
readonly meet: (x: A, y: A) => A;
}
interface Lattice<A> extends JoinSemilattice<A>, MeetSemilattice<A> {}
interface BoundedJoinSemilattice<A> extends JoinSemilattice<A> {
readonly zero: A;
}
interface BoundedMeetSemilattice<A> extends MeetSemilattice<A> {
readonly one: A;
}
interface BoundedLattice<A> extends Lattice<A>, BoundedJoinSemilattice<A>, BoundedMeetSemilattice<A> {}
interface DistributiveLattice<A> extends Lattice<A> {}
interface BoundedDistributiveLattice<A> extends BoundedLattice<A>, DistributiveLattice<A> {}Lattice with implication operation.
interface HeytingAlgebra<A> extends BoundedDistributiveLattice<A> {
readonly implies: (x: A, y: A) => A;
readonly not: (a: A) => A;
}
/**
* Heyting algebra for boolean values
*/
const heytingAlgebraBoolean: HeytingAlgebra<boolean>;Heyting algebra where not(not(a)) = a.
interface BooleanAlgebra<A> extends HeytingAlgebra<A> {}
/**
* Boolean algebra for boolean values
*/
const booleanAlgebraBoolean: BooleanAlgebra<boolean>;
/**
* Boolean algebra for void (trivial)
*/
const booleanAlgebraVoid: BooleanAlgebra<void>;Helper functions for working with algebraic structures.
/**
* Fold array using semigroup, returning Option
* @param S - Semigroup instance
* @returns Function that folds non-empty arrays
*/
function fold<A>(S: Semigroup<A>): (as: Array<A>) => Option<A>;
/**
* Get first semigroup (returns first non-empty value)
* @returns Semigroup that prefers first value
*/
function getFirstSemigroup<A>(): Semigroup<Option<A>>;
/**
* Get last semigroup (returns last non-empty value)
* @returns Semigroup that prefers last value
*/
function getLastSemigroup<A>(): Semigroup<Option<A>>;
/**
* Min semigroup using ordering
* @param O - Ordering instance
* @returns Semigroup that returns minimum value
*/
function getMinSemigroup<A>(O: Ord<A>): Semigroup<A>;
/**
* Max semigroup using ordering
* @param O - Ordering instance
* @returns Semigroup that returns maximum value
*/
function getMaxSemigroup<A>(O: Ord<A>): Semigroup<A>;
/**
* Product all numbers in array
* @param ns - Array of numbers
* @returns Product of all numbers (1 for empty array)
*/
function product(ns: Array<number>): number;
/**
* Sum all numbers in array
* @param ns - Array of numbers
* @returns Sum of all numbers (0 for empty array)
*/
function sum(ns: Array<number>): number;Usage Examples:
import { fold, getMinSemigroup, getMaxSemigroup, sum, product } from "fp-ts/lib/Semigroup";
import { ordNumber } from "fp-ts/lib/Ord";
import { some, none } from "fp-ts/lib/Option";
// Fold with semigroup
const minSemigroup = getMinSemigroup(ordNumber);
const numbers = [5, 2, 8, 1, 9];
const minimum = fold(minSemigroup)(numbers); // Some(1)
const emptyMin = fold(minSemigroup)([]); // None
// Utility functions
const total = sum([1, 2, 3, 4, 5]); // 15
const prod = product([2, 3, 4]); // 24
const emptySum = sum([]); // 0
const emptyProd = product([]); // 1