Semigroup overview

If a type A can form a Semigroup it has an associative binary operation.

interface Semigroup<A> {
  readonly concat: (x: A, y: A) => A
}

Associativity means the following equality must hold for any choice of x, y, and z.

concat(x, concat(y, z)) = concat(concat(x, y), z)

A common example of a semigroup is the type string with the operation +.

import { Semigroup } from 'fp-ts/Semigroup'

const semigroupString: Semigroup<string> = {
  concat: (x, y) => x + y,
}

const x = 'x'
const y = 'y'
const z = 'z'

semigroupString.concat(x, y) // 'xy'

semigroupString.concat(x, semigroupString.concat(y, z)) // 'xyz'

semigroupString.concat(semigroupString.concat(x, y), z) // 'xyz'

Adapted from https://typelevel.org/cats

Added in v2.0.0


Table of contents


instances

getDualSemigroup

The dual of a Semigroup, obtained by swapping the arguments of concat.

Signature

export declare function getDualSemigroup<A>(S: Semigroup<A>): Semigroup<A>

Example

import * as S from 'fp-ts/Semigroup'

assert.deepStrictEqual(S.getDualSemigroup(S.semigroupString).concat('a', 'b'), 'ba')

Added in v2.0.0

getFirstSemigroup

Always return the first argument.

Signature

export declare function getFirstSemigroup<A = never>(): Semigroup<A>

Example

import * as S from 'fp-ts/Semigroup'

assert.deepStrictEqual(S.getFirstSemigroup<number>().concat(1, 2), 1)

Added in v2.0.0

getFunctionSemigroup

Unary functions form a semigroup as long as you can provide a semigroup for the codomain.

Signature

export declare function getFunctionSemigroup<S>(S: Semigroup<S>): <A = never>() => Semigroup<(a: A) => S>

Example

import { Predicate } from 'fp-ts/function'
import * as S from 'fp-ts/Semigroup'

const f: Predicate<number> = (n) => n <= 2
const g: Predicate<number> = (n) => n >= 0

const S1 = S.getFunctionSemigroup(S.semigroupAll)<number>()

assert.deepStrictEqual(S1.concat(f, g)(1), true)
assert.deepStrictEqual(S1.concat(f, g)(3), false)

const S2 = S.getFunctionSemigroup(S.semigroupAny)<number>()

assert.deepStrictEqual(S2.concat(f, g)(1), true)
assert.deepStrictEqual(S2.concat(f, g)(3), true)

Added in v2.0.0

getIntercalateSemigroup

You can glue items between and stay associative.

Signature

export declare function getIntercalateSemigroup<A>(a: A): (S: Semigroup<A>) => Semigroup<A>

Example

import * as S from 'fp-ts/Semigroup'

const S1 = S.getIntercalateSemigroup(' ')(S.semigroupString)

assert.strictEqual(S1.concat('a', 'b'), 'a b')
assert.strictEqual(S1.concat(S1.concat('a', 'b'), 'c'), S1.concat('a', S1.concat('b', 'c')))

Added in v2.5.0

getJoinSemigroup

Get a semigroup where concat will return the maximum, based on the provided order.

Signature

export declare function getJoinSemigroup<A>(O: Ord<A>): Semigroup<A>

Example

import * as O from 'fp-ts/Ord'
import * as S from 'fp-ts/Semigroup'

const S1 = S.getJoinSemigroup(O.ordNumber)

assert.deepStrictEqual(S1.concat(1, 2), 2)

Added in v2.0.0

getLastSemigroup

Always return the last argument.

Signature

export declare function getLastSemigroup<A = never>(): Semigroup<A>

Example

import * as S from 'fp-ts/Semigroup'

assert.deepStrictEqual(S.getLastSemigroup<number>().concat(1, 2), 2)

Added in v2.0.0

getMeetSemigroup

Get a semigroup where concat will return the minimum, based on the provided order.

Signature

export declare function getMeetSemigroup<A>(O: Ord<A>): Semigroup<A>

Example

import * as O from 'fp-ts/Ord'
import * as S from 'fp-ts/Semigroup'

const S1 = S.getMeetSemigroup(O.ordNumber)

assert.deepStrictEqual(S1.concat(1, 2), 1)

Added in v2.0.0

getObjectSemigroup

Return a semigroup for objects, preserving their type.

Signature

export declare function getObjectSemigroup<A extends object = never>(): Semigroup<A>

Example

import * as S from 'fp-ts/Semigroup'

interface Person {
  name: string
  age: number
}

const S1 = S.getObjectSemigroup<Person>()
assert.deepStrictEqual(S1.concat({ name: 'name', age: 23 }, { name: 'name', age: 24 }), { name: 'name', age: 24 })

Added in v2.0.0

getStructSemigroup

Given a struct of semigroups returns a semigroup for the struct.

Signature

export declare function getStructSemigroup<O extends ReadonlyRecord<string, any>>(
  semigroups: { [K in keyof O]: Semigroup<O[K]> }
): Semigroup<O>

Example

import * as S from 'fp-ts/Semigroup'

interface Point {
  readonly x: number
  readonly y: number
}

const semigroupPoint = S.getStructSemigroup<Point>({
  x: S.semigroupSum,
  y: S.semigroupSum,
})

assert.deepStrictEqual(semigroupPoint.concat({ x: 1, y: 2 }, { x: 3, y: 4 }), { x: 4, y: 6 })

Added in v2.0.0

getTupleSemigroup

Given a tuple of semigroups returns a semigroup for the tuple.

Signature

export declare function getTupleSemigroup<T extends ReadonlyArray<Semigroup<any>>>(
  ...semigroups: T
): Semigroup<{ [K in keyof T]: T[K] extends Semigroup<infer A> ? A : never }>

Example

import * as S from 'fp-ts/Semigroup'

const S1 = S.getTupleSemigroup(S.semigroupString, S.semigroupSum)
assert.deepStrictEqual(S1.concat(['a', 1], ['b', 2]), ['ab', 3])

const S2 = S.getTupleSemigroup(S.semigroupString, S.semigroupSum, S.semigroupAll)
assert.deepStrictEqual(S2.concat(['a', 1, true], ['b', 2, false]), ['ab', 3, false])

Added in v2.0.0

semigroupAll

boolean semigroup under conjunction.

Signature

export declare const semigroupAll: Semigroup<boolean>

Example

import * as S from 'fp-ts/Semigroup'

assert.deepStrictEqual(S.semigroupAll.concat(true, true), true)
assert.deepStrictEqual(S.semigroupAll.concat(true, false), false)

Added in v2.0.0

semigroupAny

boolean semigroup under disjunction.

Signature

export declare const semigroupAny: Semigroup<boolean>

Example

import * as S from 'fp-ts/Semigroup'

assert.deepStrictEqual(S.semigroupAny.concat(true, true), true)
assert.deepStrictEqual(S.semigroupAny.concat(true, false), true)
assert.deepStrictEqual(S.semigroupAny.concat(false, false), false)

Added in v2.0.0

semigroupProduct

number semigroup under multiplication.

Signature

export declare const semigroupProduct: Semigroup<number>

Example

import * as S from 'fp-ts/Semigroup'

assert.deepStrictEqual(S.semigroupProduct.concat(2, 3), 6)

Added in v2.0.0

semigroupString

string semigroup under concatenation.

Signature

export declare const semigroupString: Semigroup<string>

Example

import * as S from 'fp-ts/Semigroup'

assert.deepStrictEqual(S.semigroupString.concat('a', 'b'), 'ab')

Added in v2.0.0

semigroupSum

number semigroup under addition.

Signature

export declare const semigroupSum: Semigroup<number>

Example

import * as S from 'fp-ts/Semigroup'

assert.deepStrictEqual(S.semigroupSum.concat(2, 3), 5)

Added in v2.0.0

semigroupVoid

Signature

export declare const semigroupVoid: Semigroup<void>

Added in v2.0.0

type classes

Semigroup (interface)

Signature

export interface Semigroup<A> extends Magma<A> {}

Added in v2.0.0

utils

fold

Given a sequence of as, concat them and return the total.

If as is empty, return the provided startWith value.

Signature

export declare function fold<A>(
  S: Semigroup<A>
): {
  (startWith: A): (as: ReadonlyArray<A>) => A
  (startWith: A, as: ReadonlyArray<A>): A
}

Example

import * as S from 'fp-ts/Semigroup'

const sum = S.fold(S.semigroupSum)(0)

assert.deepStrictEqual(sum([1, 2, 3]), 6)
assert.deepStrictEqual(sum([]), 0)

Added in v2.0.0