UNPKG

fp-ts

Version:

Functional programming in TypeScript

353 lines (352 loc) 9.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getIntercalateSemigroup = exports.semigroupVoid = exports.semigroupString = exports.semigroupProduct = exports.semigroupSum = exports.semigroupAny = exports.semigroupAll = exports.getObjectSemigroup = exports.getJoinSemigroup = exports.getMeetSemigroup = exports.getStructSemigroup = exports.getFunctionSemigroup = exports.getDualSemigroup = exports.getTupleSemigroup = exports.getLastSemigroup = exports.getFirstSemigroup = exports.fold = void 0; /** * If a type `A` can form a `Semigroup` it has an **associative** binary operation. * * ```ts * 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`. * * ```ts * concat(x, concat(y, z)) = concat(concat(x, y), z) * ``` * * A common example of a semigroup is the type `string` with the operation `+`. * * ```ts * 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* * * @since 2.0.0 */ var function_1 = require("./function"); var Ord_1 = require("./Ord"); function fold(S) { return function (startWith, as) { if (as === undefined) { var foldS_1 = fold(S); return function (as) { return foldS_1(startWith, as); }; } return as.reduce(S.concat, startWith); }; } exports.fold = fold; /** * Always return the first argument. * * @example * import * as S from 'fp-ts/Semigroup' * * assert.deepStrictEqual(S.getFirstSemigroup<number>().concat(1, 2), 1) * * @category instances * @since 2.0.0 */ function getFirstSemigroup() { return { concat: function_1.identity }; } exports.getFirstSemigroup = getFirstSemigroup; /** * Always return the last argument. * * @example * import * as S from 'fp-ts/Semigroup' * * assert.deepStrictEqual(S.getLastSemigroup<number>().concat(1, 2), 2) * * @category instances * @since 2.0.0 */ function getLastSemigroup() { return { concat: function (_, y) { return y; } }; } exports.getLastSemigroup = getLastSemigroup; /** * Given a tuple of semigroups returns a semigroup for the tuple. * * @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]) * * @category instances * @since 2.0.0 */ function getTupleSemigroup() { var semigroups = []; for (var _i = 0; _i < arguments.length; _i++) { semigroups[_i] = arguments[_i]; } return { concat: function (x, y) { return semigroups.map(function (s, i) { return s.concat(x[i], y[i]); }); } }; } exports.getTupleSemigroup = getTupleSemigroup; /** * The dual of a `Semigroup`, obtained by swapping the arguments of `concat`. * * @example * import * as S from 'fp-ts/Semigroup' * * assert.deepStrictEqual(S.getDualSemigroup(S.semigroupString).concat('a', 'b'), 'ba') * * @category instances * @since 2.0.0 */ function getDualSemigroup(S) { return { concat: function (x, y) { return S.concat(y, x); } }; } exports.getDualSemigroup = getDualSemigroup; /** * Unary functions form a semigroup as long as you can provide a semigroup for the codomain. * * @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) * * @category instances * @since 2.0.0 */ function getFunctionSemigroup(S) { return function () { return ({ concat: function (f, g) { return function (a) { return S.concat(f(a), g(a)); }; } }); }; } exports.getFunctionSemigroup = getFunctionSemigroup; /** * Given a struct of semigroups returns a semigroup for the struct. * * @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 }) * * @category instances * @since 2.0.0 */ function getStructSemigroup(semigroups) { return { concat: function (x, y) { var r = {}; for (var _i = 0, _a = Object.keys(semigroups); _i < _a.length; _i++) { var key = _a[_i]; r[key] = semigroups[key].concat(x[key], y[key]); } return r; } }; } exports.getStructSemigroup = getStructSemigroup; /** * Get a semigroup where `concat` will return the minimum, based on the provided order. * * @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) * * @category instances * @since 2.0.0 */ function getMeetSemigroup(O) { return { concat: Ord_1.min(O) }; } exports.getMeetSemigroup = getMeetSemigroup; /** * Get a semigroup where `concat` will return the maximum, based on the provided order. * * @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) * * @category instances * @since 2.0.0 */ function getJoinSemigroup(O) { return { concat: Ord_1.max(O) }; } exports.getJoinSemigroup = getJoinSemigroup; /** * Return a semigroup for objects, preserving their type. * * @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 }) * * @category instances * @since 2.0.0 */ function getObjectSemigroup() { return { concat: function (x, y) { return Object.assign({}, x, y); } }; } exports.getObjectSemigroup = getObjectSemigroup; /** * `boolean` semigroup under conjunction. * * @example * import * as S from 'fp-ts/Semigroup' * * assert.deepStrictEqual(S.semigroupAll.concat(true, true), true) * assert.deepStrictEqual(S.semigroupAll.concat(true, false), false) * * @category instances * @since 2.0.0 */ exports.semigroupAll = { concat: function (x, y) { return x && y; } }; /** * `boolean` semigroup under disjunction. * * @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) * * @category instances * @since 2.0.0 */ exports.semigroupAny = { concat: function (x, y) { return x || y; } }; /** * `number` semigroup under addition. * * @example * import * as S from 'fp-ts/Semigroup' * * assert.deepStrictEqual(S.semigroupSum.concat(2, 3), 5) * * @category instances * @since 2.0.0 */ exports.semigroupSum = { concat: function (x, y) { return x + y; } }; /** * `number` semigroup under multiplication. * * @example * import * as S from 'fp-ts/Semigroup' * * assert.deepStrictEqual(S.semigroupProduct.concat(2, 3), 6) * * @category instances * @since 2.0.0 */ exports.semigroupProduct = { concat: function (x, y) { return x * y; } }; /** * `string` semigroup under concatenation. * * @example * import * as S from 'fp-ts/Semigroup' * * assert.deepStrictEqual(S.semigroupString.concat('a', 'b'), 'ab') * * @category instances * @since 2.0.0 */ exports.semigroupString = { concat: function (x, y) { return x + y; } }; /** * @category instances * @since 2.0.0 */ exports.semigroupVoid = { concat: function () { return undefined; } }; /** * You can glue items between and stay associative. * * @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'))) * * @category instances * @since 2.5.0 */ function getIntercalateSemigroup(a) { return function (S) { return ({ concat: function (x, y) { return S.concat(x, S.concat(a, y)); } }); }; } exports.getIntercalateSemigroup = getIntercalateSemigroup;