@7urtle/lambda
Version:
Functional programming library in JavaScript.
982 lines (937 loc) • 25.7 kB
JavaScript
import { typeOf, lengthOf, deepInspect } from "./utils.js";
import { everyOf, someOf } from './list.js';
import { nary } from "./arity.js";
/**
* and is a boolean-type function composition
* where each boolean function is '&&'d together.
*
* The boolean functions may be entered in any order.
*
* and can be used together with or to encapsulate a predicate in a single function.
*
* @HindleyMilner and :: [(a -> boolean)] -> a -> boolean
*
* @pure
* @param {function} predicates
* @param {*} anything
* @return {*}
*
* @example
* import {and, isGreaterThan, isLessThan} from '@7urtle/lambda';
*
* const isEven = number => number % 2 === 0;
*
* const isSingleEvenDigit = and(isEven, isGreaterThan(-10), isLessThan(10));
* isSingleEvenDigit(8)
* // => true
*/
export const and = (...predicates) => anything => everyOf(predicate => predicate(anything))(predicates);
/**
* or is a boolean-type function composition
* where each boolean function is '||'d together.
*
* The boolean functions may be entered in any order.
*
* or can be used together with and to encapsulate a predicate in a single function.
*
* @HindleyMilner or :: [(a -> boolean)] -> a -> boolean
*
* @pure
* @param {function} predicates
* @param {*} anything
* @return {*}
*
* @example
* import {or} from '@7urtle/lambda';
*
* const isDivisibleBy = divisor => number => number % divisor === 0;
* const isFizzBuzzNumber = or(isDivisibleBy(3), isDivisibleBy(5));
*
* isFizzBuzzNumber(15)
* // => true
*/
export const or = (...predicates) => anything => someOf(predicate => predicate(anything))(predicates);
/**
* isEqual output is true if strict equality between a and b is true. isEqual output is always false for comparison
* of objects and arrays.
*
* isEqual can be called both as a curried unary function or as a standard binary function.
*
* @HindleyMilner isEqual :: a -> b -> boolean
*
* @pure
* @param {*} a
* @param {*} b
* @return {boolean}
*
* @example
* import {isEqual} from '@7urtle/lambda';
*
* isEqual('something')('something'); // => true
* isEqual('something')('something else'); // => false
* isEqual(['a'])(['a']); // => false
* isEqual({a : 'something'})({a : 'something'}); // => false
* isEqual([])([]); // => false
* isEqual([])([]); // => false
*
* // isEqual can be called both as a curried unary function or as a standard binary function
* isEqual('something')('something') === isEqual('something', 'something');
*/
export const isEqual = nary(a => b => a === b);
/**
* isNotEqual output is true if strict equality between a and b is false. isNotEqual output is always true for
* comparison of objects and arrays.
*
* isEqual can be called both as a curried unary function or as a standard binary function.
*
* @HindleyMilner isNotEqual :: a -> b -> boolean
*
* @pure
* @param {*} a
* @param {*} b
* @return {boolean}
*
* @example
* import {isNotEqual} from '@7urtle/lambda';
*
* isNotEqual('something')('something'); // => false
* isNotEqual('something')('something else'); // => true
* isNotEqual(['a'])(['a']); // => true
* isNotEqual({a : 'something'})({a : 'something'}); // => true
* isNotEqual([])([]); // => true
* isNotEqual([])([]); // => true
*
* // isNotEqual can be called both as a curried unary function or as a standard binary function
* isNotEqual('something')('something else') === isNotEqual('something', 'something else');
*/
export const isNotEqual = nary(a => b => a !== b);
/**
* isDeepEqual output is true if strict equality between the string conversion of a and the string conversion of b
* is true including arrays and objects.
*
* isDeepEqual can be called both as a curried unary function or as a standard binary function.
*
* @HindleyMilner isDeepEqual :: a -> b -> boolean
*
* @pure
* @param {*} a
* @param {*} b
* @return {boolean}
*
* @example
* import {isDeepEqual} from '@7urtle/lambda';
*
* isDeepEqual('something')('something'); // => true
* isDeepEqual('something')('something else'); // => false
* isDeepEqual(['a'])(['a']); // => true
* isDeepEqual({a : 'something'})({a : 'something'}); // => true
* isDeepEqual([])([]); // => true
* isDeepEqual([])([]); // => true
*
* // isDeepEqual can be called both as a curried unary function or as a standard binary function
* isDeepEqual('something')('something') === isDeepEqual('something', 'something');
*/
export const isDeepEqual = nary(a => b => isEqual(deepInspect(a))(deepInspect(b)));
/**
* isNotDeepEqual output is true if strict equality between the string conversion of a and the string conversion of b
* is false including arrays and objects.
*
* isNotDeepEqual can be called both as a curried unary function or as a standard binary function.
*
* @HindleyMilner isNotDeepEqual :: a -> b -> boolean
*
* @pure
* @param {*} a
* @param {*} b
* @return {boolean}
*
* @example
* import {isNotDeepEqual} from '@7urtle/lambda';
*
* isNotDeepEqual('something')('something'); // => false
* isNotDeepEqual('something')('something else'); // => true
* isNotDeepEqual(['a', 'b'])(['a']); // => true
* isNotDeepEqual({a : 'something', b: c => c})({a : 'something'}); // => true
* isNotDeepEqual([])([]); // => false
* isNotDeepEqual([])([]); // => false
*
* // isNotDeepEqual can be called both as a curried unary function or as a standard binary function
* isNotDeepEqual('something')('something else') === isNotDeepEqual('something', 'something else');
*/
export const isNotDeepEqual = nary(a => b => isNotEqual(deepInspect(a))(deepInspect(b)));
/**
* isTrue output is true if input is true.
*
* @HindleyMilner isTrue :: a -> boolean
*
* @pure
* @param {*} anything
* @return {boolean}
*
* @example
* import {isTrue} from '@7urtle/lambda';
*
* isTrue(true); // => true
* isTrue(false); // => false
*/
export const isTrue = isEqual(true);
/**
* isFalse output is true if input is false.
*
* @HindleyMilner isFalse :: a -> Boolean
*
* @pure
* @param {*} anything
* @return {boolean}
*
* @example
* import {isFalse} from '@7urtle/lambda';
*
* isFalse(true); // => false
* isFalse(false); // => true
*/
export const isFalse = isEqual(false);
/**
* isGreaterThan output is true if b is greater than a.
*
* isGreaterThan can be called both as a curried unary function or as a standard binary function.
*
* @HindleyMilner isGreaterThan :: a -> b -> boolean
*
* @pure
* @param {number} a
* @param {number} b
* @return {boolean}
*
* @example
* import {isGreaterThan} from '@7urtle/lambda';
*
* isGreaterThan(1)(2); // => true
* isGreaterThan(3)(2); // => false
*
* // isGreaterThan can be called both as a curried unary function or as a standard binary function
* isGreaterThan(1)(2) === isGreaterThan(1, 2);
*/
export const isGreaterThan = nary(a => b => b > a);
/**
* isLessThan output is true if b is less than a.
*
* isLessThan can be called both as a curried unary function or as a standard binary function.
*
* @HindleyMilner isLessThan :: a -> b -> boolean
*
* @pure
* @param {number} a
* @param {number} b
* @return {boolean}
*
* @example
* import {isLessThan} from '@7urtle/lambda';
*
* isLessThan(1)(2); // => false
* isLessThan(3)(2); // => true
*
* // isLessThan can be called both as a curried unary function or as a standard binary function
* isLessThan(3)(2) === isLessThan(3, 2);
*/
export const isLessThan = nary(a => b => b < a);
/**
* isAtLeast output is true if b is greater or equal to a.
*
* isAtLeast can be called both as a curried unary function or as a standard binary function.
*
* @HindleyMilner isAtLeast :: a -> b -> boolean
*
* @pure
* @param {number} a
* @param {number} b
* @return {boolean}
*
* @example
* import {isAtLeast} from '@7urtle/lambda';
*
* isAtLeast(1)(2); // => true
* isAtLeast(2)(2); // => true
* isAtLeast(3)(2); // => false
*
* // isAtLeast can be called both as a curried unary function or as a standard binary function
* isAtLeast(1)(2) === isAtLeast(1, 2);
*/
export const isAtLeast = nary(a => b => b >= a);
/**
* isAtMost output is true if b is less or equal to a.
*
* isAtMost can be called both as a curried unary function or as a standard binary function.
*
* @HindleyMilner isAtMost :: a -> b -> boolean
*
* @pure
* @param {number} a
* @param {number} b
* @return {boolean}
*
* @example
* import {isAtMost} from '@7urtle/lambda';
*
* isAtMost(1)(2); // => false
* isAtMost(2)(2); // => true
* isAtMost(3)(2); // => true
*
* // isAtLeast can be called both as a curried unary function or as a standard binary function
* isAtMost(3)(2) === isAtMost(31, 2);
*/
export const isAtMost = nary(a => b => b <= a);
/**
* isBetween output is true if c is between a and b.
*
* isBetween can be called both as a curried unary function or as a standard ternary function.
*
* @HindleyMilner isBetween :: a -> b -> c -> boolean
*
* @pure
* @param {number} a
* @param {number} b
* @param {number} c
* @return {boolean}
*
* @example
* import {isBetween} from '@7urtle/lambda';
*
* isBetween(1)(3)(2); // => true
* isBetween(3)(1)(2); // => true
* isBetween(1)(3)(3); // => false
* isBetween(1)(3)(4); // => false
*
* // isBetween can be called both as a curried unary function or as a standard ternary function
* isBetween(1)(3)(2) === isBetween(1, 3, 2);
*/
export const isBetween = nary(a => b => c =>
a > b
? a > c && b < c
: a < c && b > c
);
/**
* isInRange output is true if c is in range of a and b.
*
* isInRange can be called both as a curried unary function or as a standard ternary function.
*
* @HindleyMilner isInRange :: a -> b -> c -> boolean
*
* @pure
* @param {number} a
* @param {number} b
* @param {number} c
* @return {boolean}
*
* @example
* import {isInRange} from '@7urtle/lambda';
*
* isInRange(1)(3)(2); // => true
* isInRange(3)(1)(2); // => true
* isInRange(1)(3)(3); // => true
* isInRange(1)(3)(4); // => false
*
* // isInRange can be called both as a curried unary function or as a standard ternary function
* isInRange(1)(3)(2) === isInRange(1, 3, 2);
*/
export const isInRange = nary(a => b => c =>
a > b
? a >= c && b <= c
: a <= c && b >= c
);
/**
* isTypeOf output is true if b is a type of a.
*
* isTypeOf can be called both as a curried unary function or as a standard binary function.
*
* @HindleyMilner isTypeOf :: a -> b -> boolean
*
* @pure
* @param {*} a
* @param {*} b
* @return {boolean}
*
* @example
* import {isTypeOf} from '@7urtle/lambda';
*
* isTypeOf('number')(1); // => true
* isTypeOf('string')(1); // => false
*
* // isTypeOf can be called both as a curried unary function or as a standard binary function
* isTypeOf('number')(1) === isTypeOf('number', 1);
*/
export const isTypeOf = nary(a => b => isEqual(typeOf(b))(a));
/**
* isNotTypeOf output is true if b is not a type of a.
*
* isNotTypeOf can be called both as a curried unary function or as a standard binary function.
*
* @HindleyMilner isNotTypeOf :: a -> b -> boolean
*
* @pure
* @param {*} a
* @param {*} b
* @return {boolean}
*
* @example
* import {isNotTypeOf} from '@7urtle/lambda';
*
* isNotTypeOf('number')(1); // => false
* isNotTypeOf('string')(1); // => true
*
* // isNotTypeOf can be called both as a curried unary function or as a standard binary function
* isNotTypeOf('string')(1) === isNotTypeOf('string', 1);
*/
export const isNotTypeOf = nary(a => b => isNotEqual(typeOf(b))(a));
/**
* isString output is true if input is a string.
*
* @HindleyMilner isString :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isString} from '@7urtle/lambda';
*
* isString('string'); // => true
* isString(1); // => false
*/
export const isString = isTypeOf('string');
/**
* isNotString output is true if input is not a string.
*
* @HindleyMilner isNotString :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isNotString} from '@7urtle/lambda';
*
* isNotString('string'); // => false
* isNotString(1); // => true
*/
export const isNotString = isNotTypeOf('string');
/**
* isBoolean output is true if input is a boolean.
*
* @HindleyMilner isBoolean :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isBoolean} from '@7urtle/lambda';
*
* isBoolean(false); // => true
* isBoolean(1); // => false
*/
export const isBoolean = isTypeOf('boolean');
/**
* isNotBoolean output is true if input is not a boolean.
*
* @HindleyMilner isNotBoolean :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isNotBoolean} from '@7urtle/lambda';
*
* isNotBoolean(false); // => false
* isNotBoolean(1); // => true
*/
export const isNotBoolean = isNotTypeOf('boolean');
/**
* isNull output is true if input is a null.
*
* @HindleyMilner isNull :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isNull} from '@7urtle/lambda';
*
* isNull(null); // => true
* isNull(1); // => false
*/
export const isNull = isEqual(null);
/**
* isNotNull output is true if input is not a null.
*
* @HindleyMilner isNotNull :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isNotNull} from '@7urtle/lambda';
*
* isNotNull(null); // => false
* isNotNull(1); // => true
*/
export const isNotNull = isNotEqual(null);
/**
* isUndefined output is true if input is an undefined.
*
* @HindleyMilner isUndefined :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isUndefined} from '@7urtle/lambda';
*
* isUndefined(undefined); // => true
* isUndefined(1); // => false
*/
export const isUndefined = isTypeOf('undefined');
/**
* isNotUndefined output is true if input is not an undefined.
*
* @HindleyMilner isNotUndefined :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isNotUndefined} from '@7urtle/lambda';
*
* isNotUndefined(undefined); // => false
* isNotUndefined(1); // => true
*/
export const isNotUndefined = isNotTypeOf('undefined');
/**
* isNumber output is true if input is a number.
*
* @HindleyMilner isNumber :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isNumber} from '@7urtle/lambda';
*
* isNumber(1); // => true
* isNumber('string'); // => false
*/
export const isNumber = isTypeOf('number');
/**
* isNotNumber output is true if input is not a number.
*
* @HindleyMilner isNotNumber :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isNotNumber} from '@7urtle/lambda';
*
* isNotNumber(1); // => false
* isNotNumber('string'); // => true
*/
export const isNotNumber = isNotTypeOf('number');
/**
* isObject output is true if b is an object, array, or null.
*
* @HindleyMilner isObject :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isObject} from '@7urtle/lambda';
*
* isObject({}); // => true
* isObject([]); // => true
* isObject(null); // => true
* isObject(1); // => false
*/
export const isObject = isTypeOf('object');
/**
* isNotObject output is true if input is not an object, array, or null.
*
* @HindleyMilner isNotObject :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isNotObject} from '@7urtle/lambda';
*
* isNotObject({}); // => false
* isNotObject([]); // => false
* isNotObject(null); // => false
* isNotObject(1); // => true
*/
export const isNotObject = isNotTypeOf('object');
/**
* isArray output is true if input is an array.
*
* @HindleyMilner isArray :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isArray} from '@7urtle/lambda';
*
* isArray([]); // => true
* isArray({}); // => false
*/
export const isArray = Array.isArray;
/**
* isNotArray output is true if input is not an array.
*
* @HindleyMilner isNotArray :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isNotArray} from '@7urtle/lambda';
*
* isNotArray([]); // => false
* isNotArray({}); // => true
*/
export const isNotArray = a => !Array.isArray(a);
/**
* isFunction output is true if input is a function.
*
* @HindleyMilner isFunction :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isFunction} from '@7urtle/lambda';
*
* isFunction(() => null); // => true
* isFunction(1); // => false
*/
export const isFunction = isTypeOf('function');
/**
* isNotFunction output is true if input is not a function.
*
* @HindleyMilner isNotFunction :: a -> boolean
*
* @pure
* @param {*} a
* @return {boolean}
*
* @example
* import {isNotFunction} from '@7urtle/lambda';
*
* isNotFunction(() => null); // => false
* isNotFunction(1); // => true
*/
export const isNotFunction = isNotTypeOf('function');
/**
* isLength output is true if b is a length of a.
*
* @HindleyMilner isLength :: (string|array) -> b -> boolean
*
* @pure
* @param {string|array} a
* @param {number} b
* @return {boolean}
*
* @example
* import {isLength} from '@7urtle/lambda';
*
* isLength(3)('abc'); // => true
* isLength(3)([1,2,3]); // => true
* isLength(3)('abc'); // => false
*/
export const isLength = nary(a => b => isEqual(lengthOf(b))(a));
/**
* isNotLength output is true if b is not a length of a.
*
* The function can be called both as a unary isNotLength(a)(b) and binary isNotLength(a, b).
*
* @HindleyMilner isNotLength :: (string|array) -> b -> boolean
*
* @pure
* @param {string|array} a
* @param {number} b
* @return {boolean}
*
* @example
* import {isNotLength} from '@7urtle/lambda';
*
* isNotLength(3)('abc'); // => false
* isNotLength(3)([1,2,3]); // => false
* isNotLength(3)('abce'); // => true
*
* isNotLength(3)('abcd') === isNotLength(3, 'abcd'); // => true
*/
export const isNotLength = nary(a => b => !isLength(a)(b));
/**
* isElement output is true if input is an HTML or SVG Element. Otherwise it is false.
*
* @HindleyMilner isElement :: a -> boolean
*
* @pure
* @param {*} anything
* @return {boolean}
*
* @example
* import {isElement} from '@7urtle/lambda';
*
* isElement(document.createElement('span')); // => true
*/
export const isElement = anything =>
(typeof Element !== 'undefined' && anything instanceof Element) ||
(typeof HTMLDocument !== 'undefined' && anything instanceof HTMLDocument);
/**
* isNotElement output is true if input is not an HTML or SVG Element. Otherwise it is false.
*
* @HindleyMilner isNotElement :: a -> boolean
*
* @pure
* @param {*} anything
* @return {boolean}
*
* @example
* import {isNotElement} from '@7urtle/lambda';
*
* isNotElement(document.createElement('span')); // => false
*/
export const isNotElement = anything => !isElement(anything);
/**
* isEmpty output is true if input is an empty string, array, or object. Otherwise it is false.
*
* @HindleyMilner isEmpty :: (string|array|Element) -> boolean
*
* @pure
* @param {string|array|object} anything
* @return {boolean}
*
* @example
* import {isEmpty} from '@7urtle/lambda';
*
* isEmpty(''); // => true
* isEmpty([]); // => true
* isEmpty({}); // => true
* isEmpty('abc'); // => false
* isEmpty(document.getElementByID('image')); // => false
*/
export const isEmpty = anything =>
isLength(0)(anything) ||
isNotElement(anything) &&
(isObject(anything) ? isLength(0)(Object.getOwnPropertyNames(anything)) : false);
/**
* isNotEmpty output is false if input is an empty string, array, or object. Otherwise it is true.
*
* @HindleyMilner isNotEmpty :: (string|array|Element) -> boolean
*
* @pure
* @param {string|array|object} anything
* @return {boolean}
*
* @example
* import {isNotEmpty} from '@7urtle/lambda';
*
* isNotEmpty(''); // => false
* isNotEmpty([]); // => false
* isNotEmpty('abc'); // => true
* isNotEmpty({}); => true
* isNotEmpty(document.getElementByID('image')); // => true
*/
export const isNotEmpty = anything => !isEmpty(anything);
/**
* isZero output is true if input is 0.
*
* @HindleyMilner isZero :: a -> boolean
*
* @pure
* @param {number} a
* @return {boolean}
*
* @example
* import {isZero} from '@7urtle/lambda';
*
* isZero(0); // => true
* isZero(1); // => false
*/
export const isZero = isEqual(0);
/**
* isNotZero output is true if input is not 0.
*
* @HindleyMilner isNotZero :: a -> boolean
*
* @pure
* @param {number} a
* @return {boolean}
*
* @example
* import {isZero} from '@7urtle/lambda';
*
* isZero(0); // => false
* isZero(1); // => true
*/
export const isNotZero = isNotEqual(0);
/**
* isNothing returns true if input is null, undefined or empty string or empty array or empty object or the monad Nothing.
*
* @HindleyMilner isNothing :: a -> boolean
*
* @pure
* @param {*} anything
* @return {boolean}
*
* @example
* import { isNothing, Maybe, Just, Nothing } from '@7urtle/lambda';
*
* isNothing(null); // => true
* isNothing(undefined); // => true
* isNothing(''); // => true
* isNothing([]); // => true
* isNothing({}); // => true
* isNothing(Maybe.of('')); // => true
* isNothing(Nothing); // => true
* isNothing('7urtle'); // => false
* isNothing(Maybe.of('7urtle')); // => false
* isNothing(Just('7urtle')); // => false
*/
export const isNothing = anything =>
anything && anything.isNothing
? anything.isNothing()
: isNull(anything) || isUndefined(anything) || isEmpty(anything);
/**
* isJust returns true if input is not null, undefined or empty string or empty array or empty object.
*
* @HindleyMilner isJust :: a -> boolean
*
* @pure
* @param {*} anything
* @return {boolean}
*
* @example
* import { isJust, Maybe, Just, Nothing } from '@7urtle/lambda';
*
* isJust(null); // => false
* isJust(undefined); // => false
* isJust(''); // => false
* isJust([]); // => false
* isJust({}); // => false
* isJust(Nothing); // => false
* isJust('7urtle'); // => true
* isJust(Maybe.of('7urtle')); // => true
* isJust(Just('7urtle')); // => true
*/
export const isJust = anything =>
!isNothing(anything);
/**
* when tests anything argument by passing it to predicate function. If the predicate function is true, when
* will return the result of whenTrueFn function which receivs the same anything argument. If the predicate
* is false, then the anything argument is returned unchanged.
*
* The function can be called both as a unary when(predicate)(whenTrueFn)(anything) and ternary when(predicate, whenTrueFn, anything).
*
* @HindleyMilner when :: (a -> Boolean) -> (a -> a) -> a -> a
*
* @pure
* @param {function} predicate
* @param {function} whenTrueFn
* @param {*} anything
* @return {*}
*
* @example
* import {when} from '@7urtle/lambda';
*
* const predicate = a => a > 1;
* const whenTrueFn = a => a * 2;
*
* when(predicate)(whenTrueFn)(2); // => 4
* when(predicate)(whenTrueFn)(1); // => 1
*
* when(predicate)(whenTrueFn)(2) === when(predicate, whenTrueFn, 2); // => true
*/
export const when = nary(predicate => whenTrueFn => anything =>
predicate(anything)
? whenTrueFn(anything)
: anything
);
/**
* unless tests anything argument by passing it to predicate function. If the predicate function is false, unless
* will return the result of whenFalseFn function which receivs the same anything argument. If the predicate
* is true, then the anything argument is returned unchanged.
*
* The function can be called both as a unary unless(predicate)(whenFalseFn)(anything) and ternary unless(predicate, whenFalseFn, anything).
*
* @HindleyMilner unless :: (a -> Boolean) -> (a -> a) -> a -> a
*
* @pure
* @param {function} predicate
* @param {function} whenFalseFn
* @param {*} anything
* @return {*}
*
* @example
* import {unless} from '@7urtle/lambda';
*
* const predicate = a => a > 1;
* const whenFalseFn = a => a * 2;
*
* when(predicate)(whenFalseFn)(4); // => 4
* when(predicate)(whenFalseFn)(1); // => 2
*
* when(predicate)(whenFalseFn)(1) === when(predicate, whenFalseFn, 1); // => true
*/
export const unless = nary(predicate => whenFalseFn => anything =>
predicate(anything)
? anything
: whenFalseFn(anything)
);
/**
* ifElse tests anything argument by passing it to predicate function. If the predicate function is true, ifElse
* will return the result of whenTrueFn function which receivs the same anything argument. If the predicate
* is false, then the anything argument is passed to the whenFalseFn function.
*
* The function can be called both as a unary ifElse(predicate)(whenTrueFn)(whenFalseFn)(anything) and quaternary
* ifElse(predicate, whenTrueFn, whenFalseFn, anything).
*
* @HindleyMilner ifElse :: (a -> Boolean) -> (a -> a) -> (a -> a) a -> a
*
* @pure
* @param {function} predicate
* @param {function} whenTrueFn
* @param {function} whenFalseFn
* @param {*} anything
* @return {*}
*
* @example
* import {ifElse} from '@7urtle/lambda';
*
* const predicate = a => a > 1;
* const whenTrueFn = a => a / 2;
* const whenFalseFn = a => a * 2;
*
* ifElse(predicate)(whenTrueFn)(whenFalseFn)(4); // => 2
* ifElse(predicate)(whenTrueFn)(whenFalseFn)(1); // => 2
*
* ifElse(predicate)(whenTrueFn)(whenFalseFn)(1) === ifElse(predicate, whenTrueFn, whenFalseFn, 1); // => true
*/
export const ifElse = nary(predicate => whenTrueFn => whenFalseFn => anything =>
predicate(anything)
? whenTrueFn(anything)
: whenFalseFn(anything)
);