// ets_tracing: off import type { Equal } from "../Equal/index.js" import { makeEqual } from "../Equal/index.js" import type { Ordering } from "../Ordering/index.js" import type { ForcedTuple } from "../Utils/index.js" import type { Ord } from "./definition.js" /** * Creates Ord[A] from a compare function */ export function makeOrd(compare: (x: A, y: A) => Ordering): Ord { return { compare } } /** * Contramap Ord input */ export function contramap(f: (b: B) => A): (fa: Ord) => Ord { return (fa) => contramap_(fa, f) } /** * Contramap Ord input */ export function contramap_(fa: Ord, f: (b: B) => A): Ord { return makeOrd((x, y) => fa.compare(f(x), f(y))) } /** * Test whether one value is _strictly greater than_ another */ export function gt(O: Ord): (x: A, y: A) => boolean { return (x, y) => O.compare(x, y) === 1 } /** * Test whether one value is _non-strictly less than_ another */ export function leq(O: Ord): (x: A, y: A) => boolean { return (x, y) => O.compare(x, y) !== 1 } /** * Test whether one value is _strictly less than_ another */ export function lt(O: Ord): (x: A, y: A) => boolean { return (x, y) => O.compare(x, y) === -1 } /** * Take the maximum of two values. If they are considered equal, the first argument is chosen */ export function max(O: Ord): (x: A, y: A) => A { return (x, y) => (O.compare(x, y) === -1 ? y : x) } /** * Take the minimum of two values. If they are considered equal, the first argument is chosen */ export function min(O: Ord): (x: A, y: A) => A { return (x, y) => (O.compare(x, y) === 1 ? y : x) } /** * Test whether a value is between a minimum and a maximum (inclusive) */ export function between(O: Ord): (low: A, hi: A) => (x: A) => boolean { const lessThanO = lt(O) const greaterThanO = gt(O) return (low, hi) => (x) => lessThanO(x, low) || greaterThanO(x, hi) ? false : true } /** * Clamp a value between a minimum and a maximum */ export function clamp(O: Ord): (low: A, hi: A) => (x: A) => A { const minO = min(O) const maxO = max(O) return (low, hi) => (x) => maxO(minO(x, hi), low) } /** * Get the dual of an Ord */ export function inverted(O: Ord) { return makeOrd((x, y) => O.compare(y, x)) } /** * Get an instance of Equal */ export function getEqual(O: Ord): Equal { return makeEqual((x, y) => O.compare(x, y) === 0) } /** * Given a tuple of `Ord`s returns an `Ord` for the tuple */ export function tuple>>( ...ords: T ): Ord< ForcedTuple<{ [K in keyof T]: T[K] extends Ord ? A : never }> > { return makeOrd((x, y) => { let i = 0 for (; i < ords.length - 1; i++) { const r = ords[i]!.compare(x.get(i), y.get(i)) if (r !== 0) { return r } } return ords[i]!.compare(x.get(i), y.get(i)) }) }