fp-ts
Version:
Functional programming in TypeScript
303 lines (302 loc) • 8.36 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ord = exports.Contravariant = exports.ordDate = exports.URI = exports.contramap = exports.getDualOrd = exports.getTupleOrd = exports.getMonoid = exports.getSemigroup = exports.fromCompare = exports.between = exports.clamp = exports.max = exports.min = exports.geq = exports.leq = exports.gt = exports.lt = exports.ordBoolean = exports.ordNumber = exports.ordString = void 0;
var Ordering_1 = require("./Ordering");
var function_1 = require("./function");
// default compare for primitive types
function compare(x, y) {
return x < y ? -1 : x > y ? 1 : 0;
}
function strictEqual(a, b) {
return a === b;
}
/**
* @category instances
* @since 2.0.0
*/
exports.ordString = {
equals: strictEqual,
compare: compare
};
/**
* @category instances
* @since 2.0.0
*/
exports.ordNumber = {
equals: strictEqual,
compare: compare
};
/**
* @category instances
* @since 2.0.0
*/
exports.ordBoolean = {
equals: strictEqual,
compare: compare
};
// TODO: curry in v3
/**
* Test whether one value is _strictly less than_ another
*
* @since 2.0.0
*/
function lt(O) {
return function (x, y) { return O.compare(x, y) === -1; };
}
exports.lt = lt;
// TODO: curry in v3
/**
* Test whether one value is _strictly greater than_ another
*
* @since 2.0.0
*/
function gt(O) {
return function (x, y) { return O.compare(x, y) === 1; };
}
exports.gt = gt;
// TODO: curry in v3
/**
* Test whether one value is _non-strictly less than_ another
*
* @since 2.0.0
*/
function leq(O) {
return function (x, y) { return O.compare(x, y) !== 1; };
}
exports.leq = leq;
// TODO: curry in v3
/**
* Test whether one value is _non-strictly greater than_ another
*
* @since 2.0.0
*/
function geq(O) {
return function (x, y) { return O.compare(x, y) !== -1; };
}
exports.geq = geq;
// TODO: curry in v3
/**
* Take the minimum of two values. If they are considered equal, the first argument is chosen
*
* @since 2.0.0
*/
function min(O) {
return function (x, y) { return (O.compare(x, y) === 1 ? y : x); };
}
exports.min = min;
// TODO: curry in v3
/**
* Take the maximum of two values. If they are considered equal, the first argument is chosen
*
* @since 2.0.0
*/
function max(O) {
return function (x, y) { return (O.compare(x, y) === -1 ? y : x); };
}
exports.max = max;
/**
* Clamp a value between a minimum and a maximum
*
* @since 2.0.0
*/
function clamp(O) {
var minO = min(O);
var maxO = max(O);
return function (low, hi) { return function (x) { return maxO(minO(x, hi), low); }; };
}
exports.clamp = clamp;
/**
* Test whether a value is between a minimum and a maximum (inclusive)
*
* @since 2.0.0
*/
function between(O) {
var lessThanO = lt(O);
var greaterThanO = gt(O);
return function (low, hi) { return function (x) { return (lessThanO(x, low) || greaterThanO(x, hi) ? false : true); }; };
}
exports.between = between;
/**
* @category constructors
* @since 2.0.0
*/
function fromCompare(compare) {
var optimizedCompare = function (x, y) { return (x === y ? 0 : compare(x, y)); };
return {
equals: function (x, y) { return optimizedCompare(x, y) === 0; },
compare: optimizedCompare
};
}
exports.fromCompare = fromCompare;
/**
* Use `getMonoid` instead
*
* @category instances
* @since 2.0.0
* @deprecated
*/
function getSemigroup() {
return {
concat: function (x, y) { return fromCompare(function (a, b) { return Ordering_1.monoidOrdering.concat(x.compare(a, b), y.compare(a, b)); }); }
};
}
exports.getSemigroup = getSemigroup;
/**
* Returns a `Monoid` such that:
*
* - its `concat(ord1, ord2)` operation will order first by `ord1`, and then by `ord2`
* - its `empty` value is an `Ord` that always considers compared elements equal
*
* @example
* import { sort } from 'fp-ts/Array'
* import { contramap, getDualOrd, getMonoid, ordBoolean, ordNumber, ordString } from 'fp-ts/Ord'
* import { pipe } from 'fp-ts/function'
* import { fold } from 'fp-ts/Monoid'
*
* interface User {
* id: number
* name: string
* age: number
* rememberMe: boolean
* }
*
* const byName = pipe(
* ordString,
* contramap((p: User) => p.name)
* )
*
* const byAge = pipe(
* ordNumber,
* contramap((p: User) => p.age)
* )
*
* const byRememberMe = pipe(
* ordBoolean,
* contramap((p: User) => p.rememberMe)
* )
*
* const M = getMonoid<User>()
*
* const users: Array<User> = [
* { id: 1, name: 'Guido', age: 47, rememberMe: false },
* { id: 2, name: 'Guido', age: 46, rememberMe: true },
* { id: 3, name: 'Giulio', age: 44, rememberMe: false },
* { id: 4, name: 'Giulio', age: 44, rememberMe: true }
* ]
*
* // sort by name, then by age, then by `rememberMe`
* const O1 = fold(M)([byName, byAge, byRememberMe])
* assert.deepStrictEqual(sort(O1)(users), [
* { id: 3, name: 'Giulio', age: 44, rememberMe: false },
* { id: 4, name: 'Giulio', age: 44, rememberMe: true },
* { id: 2, name: 'Guido', age: 46, rememberMe: true },
* { id: 1, name: 'Guido', age: 47, rememberMe: false }
* ])
*
* // now `rememberMe = true` first, then by name, then by age
* const O2 = fold(M)([getDualOrd(byRememberMe), byName, byAge])
* assert.deepStrictEqual(sort(O2)(users), [
* { id: 4, name: 'Giulio', age: 44, rememberMe: true },
* { id: 2, name: 'Guido', age: 46, rememberMe: true },
* { id: 3, name: 'Giulio', age: 44, rememberMe: false },
* { id: 1, name: 'Guido', age: 47, rememberMe: false }
* ])
*
* @category instances
* @since 2.4.0
*/
function getMonoid() {
return {
// tslint:disable-next-line: deprecation
concat: getSemigroup().concat,
empty: fromCompare(function () { return 0; })
};
}
exports.getMonoid = getMonoid;
/**
* Given a tuple of `Ord`s returns an `Ord` for the tuple
*
* @example
* import { getTupleOrd, ordString, ordNumber, ordBoolean } from 'fp-ts/Ord'
*
* const O = getTupleOrd(ordString, ordNumber, ordBoolean)
* assert.strictEqual(O.compare(['a', 1, true], ['b', 2, true]), -1)
* assert.strictEqual(O.compare(['a', 1, true], ['a', 2, true]), -1)
* assert.strictEqual(O.compare(['a', 1, true], ['a', 1, false]), 1)
*
* @category instances
* @since 2.0.0
*/
function getTupleOrd() {
var ords = [];
for (var _i = 0; _i < arguments.length; _i++) {
ords[_i] = arguments[_i];
}
var len = ords.length;
return fromCompare(function (x, y) {
var i = 0;
for (; i < len - 1; i++) {
var r = ords[i].compare(x[i], y[i]);
if (r !== 0) {
return r;
}
}
return ords[i].compare(x[i], y[i]);
});
}
exports.getTupleOrd = getTupleOrd;
/**
* @category combinators
* @since 2.0.0
*/
function getDualOrd(O) {
return fromCompare(function (x, y) { return O.compare(y, x); });
}
exports.getDualOrd = getDualOrd;
// -------------------------------------------------------------------------------------
// non-pipeables
// -------------------------------------------------------------------------------------
/* istanbul ignore next */
var contramap_ = function (fa, f) { return function_1.pipe(fa, exports.contramap(f)); };
// -------------------------------------------------------------------------------------
// pipeables
// -------------------------------------------------------------------------------------
/**
* @category Contravariant
* @since 2.0.0
*/
var contramap = function (f) { return function (fa) {
return fromCompare(function (x, y) { return fa.compare(f(x), f(y)); });
}; };
exports.contramap = contramap;
// -------------------------------------------------------------------------------------
// instances
// -------------------------------------------------------------------------------------
/**
* @category instances
* @since 2.0.0
*/
exports.URI = 'Ord';
/**
* @category instances
* @since 2.0.0
*/
exports.ordDate =
/*#__PURE__*/
function_1.pipe(exports.ordNumber,
/*#__PURE__*/
exports.contramap(function (date) { return date.valueOf(); }));
/**
* @category instances
* @since 2.7.0
*/
exports.Contravariant = {
URI: exports.URI,
contramap: contramap_
};
// TODO: remove in v3
/**
* @category instances
* @since 2.0.0
*/
exports.ord = exports.Contravariant;