// ets_tracing: off import * as Ord from "@effect-ts/system/Ord" import type { Associative } from "./definition.js" import { makeAssociative } from "./makeAssociative.js" /** * Fold `Associative` through an `Array` */ export function fold(S: Associative): (a: A) => (as: ReadonlyArray) => A { return (a) => (as) => as.reduce((x, y) => S.combine(x, y), a) } /** * `Associative` that returns first element */ export function first(): Associative { return makeAssociative((x) => x) } /** * `Associative` that returns last element */ export function last(): Associative { return makeAssociative((_, y) => y) } /** * Given a tuple of `Associative` returns an `Associative` for the tuple */ export function tuple>>( ...associatives: T ): Associative<{ [K in keyof T]: T[K] extends Associative ? A : never }> { return makeAssociative( (x, y) => associatives.map((s, i) => s.combine(x[i], y[i])) as any ) } /** * The dual of a `Associative`, obtained by swapping the arguments of `combine`. */ export function inverted(S: Associative): Associative { return makeAssociative((x, y) => S.combine(y, x)) } /** * `Associative` for function combination */ export function func(S: Associative): () => Associative<(a: A) => S> { return () => makeAssociative((f, g) => (a) => S.combine(f(a), g(a))) } /** * `Associative` for a structure */ export function struct>(associatives: { [K in keyof O]: Associative }): Associative { return makeAssociative((x, y) => { const r: any = {} for (const key of Object.keys(associatives)) { r[key] = associatives[key]!.combine(x[key], y[key]) } return r }) } /** * `Associative` that returns last `Min` of elements */ export function min(O: Ord.Ord): Associative { return makeAssociative(Ord.min(O)) } /** * `Associative` that returns last `Max` of elements */ export function max(O: Ord.Ord): Associative { return makeAssociative(Ord.max(O)) } /** * Returns a `Associative` instance for objects preserving their type */ export function object(): Associative { return makeAssociative((x, y) => Object.assign({}, x, y)) } /** * You can glue items between and stay associative */ export function intercalate(a: A): (S: Associative) => Associative { return (S) => makeAssociative((x, y) => S.combine(x, S.combine(a, y))) } export * from "./definition.js"