@7urtle/lambda
Documentation

If you want to learn how to use @7urtle/lambda or functional programming, please visit the Learn section of the website.

You can find the source code for @7urtle/lambda on GitHub under MIT open source license. All the documentation that you can see below has been generated from the code documentation there. If you find any errors or if you want to improve the documentation here, you can simply create a pull request on GitHub and contribute directly.

To get help or ask any questions please visit @7urtle/lambda GitHub Issues.

Core Functions

composecompose(fns: function)(anything: any): any

pure function compose :: [(a -> b)] -> a -> b

compose is a right-to-left function composition where each function receives input and hands over its output to the next function.

compose executes functions in reverse order to pipe.

compose(f,g)(x) is equivalent to f(g(x)).

1
import {compose} from '@7urtle/lambda';
2
3
const addA = a => a + 'A';
4
const addB = a => a + 'B';
5
const addAB = value => compose(addA, addB)(value);
6
7
addAB('Order: ');
8
// => Order: BA

concatconcat(a: any)(b: any): any

pure function concat :: a -> a|boolean

contact outputs concatenated inputs of strings, arrays and shallow objects or outputs undefined for other types.

concat can be called both as a curried unary function or as a standard binary function.

1
import {concat} from '@7urtle/lambda';
2
3
concat('cd')('ab'); // => 'abcd'
4
concat([3, 4])([1,2]); // => [1, 2, 3, 4]
5
concat({here: {here: 'there'}})({hi: 'hello'}); // => {hi: 'hello', here: {here: 'there'}}
6
concat('cd')(1); // => undefined
7
8
// concat can be called both as a curried unary function or as a standard binary function
9
concat('cd')('ab') === concat('cd', 'ab');

failfail(error: string|Error): null

function fail :: a -> b -> number

fail throws the input error. It is just a function wrapped around JavaScript throw.

1
import { fail } from '@7urtle/lambda';
2
3
fail('I am an error.'); // => throws 'I am an error.'
4
fail(new Error('something happend :(')); // => throws Error('something happened :('))

flatMapflatMap(fn: function)(functor: functor): functor

function flatMap :: (a -> Functor) -> Functor -> Functor

flatMap maps function over inputted functor outputting resulting flattened functor.

You should use flatMap when you want to work with functors using functions and functional composition rather than calling flatMaps.

The function can be called both as a unary flatMap(fn)(functor) and binary flatMap(fn, functor).

1
import {flatMap, map, Maybe} from '@7urtle/lambda';
2
3
const maybePlus2 = number => Maybe.of(number + 2);
4
5
// the function maybePlus2 is applied to the value of the functor
6
flatMap(maybePlus2)(Maybe.of(3)); // => Just(5)
7
map(maybePlus2)(Maybe.of(3)); // => Just(Just(5))
8
9
// use of flatMap equals the use of flatMap on the functor
10
flatMap(maybePlus2)(Maybe.of(3)).value === Maybe.of(3).flatMap(maybePlus2).value;
11
12
// flatMap can be called both as a curried unary function or as a standard binary function
13
flatMap(maybePlus2)(Maybe.of(3)).value === flatMap(maybePlus2, Maybe.of(3)).value;

identityidentity(anything: any): any

pure function identity :: a -> a

identity is a function that simply passes its input to its output without changing it.

1
import {identity} from '@7urtle/lambda';
2
3
identity('anything');
4
// => anything

includesincludes(a: any)(b: any): any

pure function includes :: a -> b -> boolean

includes(a)(b) output is true if b includes a.

includes can be called both as a curried unary function or as a standard binary function.

1
import {includes} from '@7urtle/lambda';
2
3
includes('rt')('7urtle'); // => true
4
includes(1)([1, 2, 3]) // => true
5
includes('turtle')([1, 2, 3]) // => false
6
7
// includes can be called both as a curried unary function or as a standard binary function
8
includes('rt')('7urtle') === includes('rt', '7urtle');

indexOfindexOf(a: any)(b: any): any

pure function indexOf :: a -> b -> number

indexOf(a)(b) outputs position of input a within input b or undefined if it is not found.

indexOf can be called both as a curried unary function or as a standard binary function.

1
import {indexOf} from '@7urtle/lambda';
2
3
indexOf('7')('7urtle'); // => 0
4
indexOf(7)('7urtle'); // => 0
5
indexOf(2)([1, 2, 3]); // => 1
6
indexOf(4)([1, 2, 3]); // => undefined
7
8
// indexOf can be called both as a curried unary function or as a standard binary function
9
indexOf('7')('7urtle') === indexOf('7', '7urtle');

lastIndexOflastIndexOf(a: any)(b: any): any

pure function lastIndexOf :: a -> b -> number

lastIndexOf(a)(b) outputs position of input a withing input b looking from the end or it retuns undefined if it is not found.

lastIndexOf can be called both as a curried unary function or as a standard binary function.

1
import {lastIndexOf} from '@7urtle/lambda';
2
3
lastIndexOf('urtle')('7urtle'); // => 1
4
lastIndexOf(2)([1, 2, 3, 2]); // => 3
5
lastIndexOf('8')('7urtle'); // => undefined
6
7
// lastIndexOf can be called both as a curried unary function or as a standard binary function
8
lastIndexOf('7')('7urtle') === lastIndexOf('7', '7urtle');

liftA2liftA2(fn: function)(ap1: functor)(ap2: functor): functor

pure function liftA2 (a -> b -> c) -> Applicative a -> Applicative b -> Applicative c

liftA2 provides point-free way of writing calls over applicative functors and functions expecting 2 inputs. It applies input function over both functors values providing a resulting functor.

The function can be called both as a unary liftA2(fn)(functor)(functor) and ternary liftA2(fn, functor, functor).

1
import {liftA2, Maybe} from '@7urtle/lambda';
2
3
const add = a => b => a + b;
4
5
// function add which expects two inputs is applied to the values of two applicative functors Maybe
6
// the result is a Maybe functor with the internal value 5
7
liftA2(add)(Maybe.of(2))(Maybe.of(3)); // => Just(5)
8
9
// an example of applying a function over a Maybe of undefined value to demonstrate continued safety of functors
10
liftA2(add)(Maybe.of(1))(Maybe.of(undefined)).isNothing(); // => true
11
12
// liftA2 can be called both as a curried unary function or as a standard ternary function
13
liftA2(add)(Maybe.of(2))(Maybe.of(3)).value === liftA2(add, Maybe.of(2), Maybe.of(3)).value;

liftA3liftA3(fn: function)(ap1: functor)(ap2: functor)(ap3: functor): functor

pure function liftA3 (a -> b -> c -> d) -> Applicative a -> Applicative b -> Applicative c -> Applicative d

liftA3 provides point-free way of writing calls over applicative functors and functions expecting 3 inputs. It applies input function over input functors values providing a resulting functor.

The function can be called both as a unary liftA3(fn)(functor)(functor)(functor) and quaternary liftA2(fn, functor, functor, functor).

1
import {liftA3, Maybe} from '@7urtle/lambda';
2
3
const add = a => b => c => a + b + c;
4
5
// function add which expects three inputs is applied to the values of three applicative functors Maybe
6
// the result is a Maybe functor with the internal value 9
7
liftA3(add)(Maybe.of(2))(Maybe.of(3))(Maybe.of(4)); // => Just(9)
8
9
// an example of applying a function over a Maybe of undefined value to demonstrate continued safety of functors
10
liftA3(add)(Maybe.of(1))(Maybe.of(2))(Maybe.of(undefined)).isNothing(); // => true
11
12
// liftA3 can be called both as a curried unary function or as a standard quaternary function
13
liftA3(add)(Maybe.of(2))(Maybe.of(3))(Maybe.of(4)).value === liftA3(add, Maybe.of(2), Maybe.of(3), Maybe.of(4)).value;

mapmap(mapper: function)(anything: any): any

function map :: (a -> b) -> a -> b

map executes mapper function over input. If the input is array or monad, their map functions are executed. If the input is anything else the mapper function is executed with the input as its argument.

In case of monads, you should use map when you want to work with functors using functions and functional composition rather than calling Functor.map.

If you need to both filter and map over an array, consider using the filterMap function.

map can be called both as a curried unary function or as a standard binary function.

1
import {map, Maybe, upperCaseOf} from '@7urtle/lambda';
2
3
const mapper = a => a + 'm';
4
const list = ['a', 'b', 'c'];
5
6
// the function mapper is applied to each member of the array
7
map(mapper)(list); // => ['am', 'bm', 'cm']
8
9
// the function upperCaseOf is applied to the value of the functor
10
map(upperCaseOf)(Maybe.of('something')); // => Just('SOMETHING')
11
12
// the function upperCaseOf is applied to the input string
13
map(upperCaseOf)('turtle'); // => 'TURTLE'
14
15
// use of map equals the use of map on the functor
16
map(upperCaseOf)(Maybe.of('something')).value === Maybe.of('something').map(upperCaseOf).value;
17
18
// map can be called both as a curried unary function or as a standard binary function
19
map(upperCaseOf)(Maybe.of('something')).value === map(upperCaseOf, Maybe.of('something')).value;

memomemo(fn: function): function

pure function memo :: (a -> b) -> (a -> b)

memo takes input function and returns it enhanced by memoization which ensures that each result is always remembered internally and executed only once.

1
import {memo} from '@7urtle/lambda';
2
3
const addTwo = a => a + 2;
4
const memoAddTwo = memo(addTwo);
5
const memoAddThree = memo(a => a + 3);
6
7
memoAddTwo(1); // => 3
8
memoAddThree(1); // => 4
9
10
let count = 0;
11
const increaseCount = () => ++count;
12
13
increaseCount(); // 1
14
increaseCount(); // 2
15
16
const memoIncreaseCount = memo(increaseCount);
17
18
memoIncreaseCount(); // 3
19
memoIncreaseCount(); // 3
20
memoIncreaseCount(); // 3

memoizememoize(memory: object)(fn: function)(anything: any): any

function memoize :: object -> (a -> b) -> a -> b

memoize uses input memory to save output of input function and then uses it to lookup the result on a repeated run. This function is not pure because the input memory is modified in the process.

The function can be called both as a curried unary function or as a standard ternary function.

1
import {memoize} from '@7urtle/lambda';
2
3
const addTwo = a => a + 2;
4
let memory = {};
5
6
memoize(memory)(addTwo)(1); // => 3
7
memoize(memory)(addTwo)(1); // => 3
8
memory[1]; // => 3
9
10
// lastIndexOf can be called both as a curried unary function or as a standard ternary function
11
memoize(memory)(addTwo)(1) === memoize(memory, addTwo, 1);

mergemerge(sources: array|object): array|object

pure function merge :: [a] -> [b]

merge performs a deep merge on all input objects and arrays.

1
import {merge} from '@7urtle/lambda';
2
3
const obj1 = { a: 'a', c: ['a'] };
4
const obj2 = { b: a => a, d: ['a', 'b'] };
5
const obj3 = { a: 'c', c: ['c'] };
6
7
merge(obj1, obj2, obj3));
8
// => {"a": "c", "b": a => a, "c": ["a", "c"], "d": ["a", "b"]}
9
10
const list1 = ['a', 'b'];
11
const list2 = [1, 2];
12
13
merge(list1,list2);
14
// => ['a', 'b', 1, 2]
15
16
merge(list1, obj1)
17
// => {"0": "a", "1": "b", "a": "a", "c": ["a"]}

pipepipe(fns: function)(anything: any): any

pure function pipe :: [(a -> b)] -> a -> b

pipe output is a left-to-right function composition where each function receives input and hands over its output to the next function.

pipe executes functions in reverse order to compose.

pipe(f,g)(x) is equivalent to g(f(x)).

1
import {pipe} from '@7urtle/lambda';
2
3
const addA = a => a + 'A';
4
const addB = a => a + 'B';
5
const addAB = value => pipe(addA, addB)(value);
6
7
addAB('Order: ');
8
// => Order: AB

Utility Functions

deepInspectdeepInspect(a: any): string

pure function deepInspect :: a -> string

deepInspect runs recursively over input and outputs string representing the input.

1
import {deepInspect} from '@7urtle/lambda';
2
3
function namedFunction() {
4
return null;
5
}
6
7
deepInspect({a: 'b'}); // => "{a: 'b'}"
8
deepInspect(namedFunction); // => 'namedFunction'
9
deepInspect([1, 'a']); // => "[1, 'a']"
10
deepInspect('my string'); // => "'my string'"
11
deepInspect(undefined); // => 'undefined'

inspectArrayinspectArray(a: array): string

pure function inspectArray :: [a] -> string

inspectArray maps over input array [a] and outputs string representing it.

1
import {inspectArray} from '@7urtle/lambda';
2
3
function namedFunction() {
4
return null;
5
}
6
7
inspectArray([1, 'a']); // => "[1, 'a']"
8
inspectArray([namedFunction, 'a']); // => "[namedFunction, 'a']"

inspectFunctioninspectFunction(fn: function): string

pure function inspectFunction :: (a -> b) -> string

inspectFunction outputs name of named function or its conversion to string.

1
import {inspectFunction} from '@7urtle/lambda';
2
3
function namedFunction() {
4
return null;
5
}
6
7
inspectFunction(namedFunction); // => 'namedFunction'
8
inspectFunction(() => 'b');
9
// => `function () {
10
// => return 'b';
11
// => }`

inspectObjectinspectObject(a: object): string

pure function inspectObject :: a -> string

inspectObject outputs string representing input.

1
import {inspectObject} from '@7urtle/lambda';
2
3
inspectObject({a: 'b'}); // => "{a: 'b'}"

inspectStringinspectString(a: any): string

pure function inspectString :: a -> string

inspectString outputs string representing input.

1
import {inspectString} from '@7urtle/lambda';
2
3
inspectString('my string'); // => "'my string'"

lengthOflengthOf(a: string|array): number

pure function lengthOf :: (string|array) -> number

lengthOf outputs the length of an input.

1
import {lengthOf} from '@7urtle/lambda';
2
3
lengthOf('7turtle'); // => 7
4
lengthOf([1,2,3]); // => 3
5
lengthOf({}); // => undefined

loglog(anything: any): any

function log :: a -> a

log output is the same as input and it logs the input value. log causes side effect of console.log.

1
import {log} from '@7urtle/lambda';
2
3
log('anything'); // => 'anything'

minusOneToUndefinedminusOneToUndefined(anything: any): any|boolean

pure function minusOneToUndefined :: a -> a|boolean

minusOneToUndefined output is the same as input or undefined if input is -1.

Because some functions return -1 as error state, this function is created to change it into a more consistent undefined output.

1
import {log} from '@7urtle/lambda';
2
3
minusOneToUndefined(-1); // => undefined
4
minusOneToUndefined(0); // => 0
5
minusOneToUndefined('7urtle'); // => '7urtle'

passThroughpassThrough(fn: function)(anything: any): boolean

pure function passThrough :: function -> a -> a

passThrough output is the same as input a. passThrough executes function passed as first argument.

passThrough can be called both as a curried unary function or as a standard binary function.

1
import {passThrough} from '@7urtle/lambda';
2
3
passThrough(() => 'b')('a'); // => 'a'
4
5
// isTypeOf can be called both as a curried unary function or as a standard binary function
6
passThrough(() => 'b')('a') === passThrough(() => 'b', 'a');

spyspy(anything: any): any

function spy :: a -> a

spy output is the same as input and it logs the deepInspect of the input. spy causes side effect of console.log.

1
import {spy} from '@7urtle/lambda';
2
3
spy([1, 'a']); // => "[1, 'a']"

typeOftypeOf(a: any): string

pure function typeOf :: a -> string

typeOf outputs a type of its input.

1
import {typeOf} from '@7urtle/lambda';
2
3
typeOf('7turtle'); // => 'string'

Arity Function

currycurry(fn: function): function

pure function curry :: (a -> b) -> a -> b

curry takes n-ary function and allows it to be called both as curried and n-ary.

1
import {curry} from '@7urtle/lambda';
2
3
const fn = curry((a, b) => a + b);
4
fn('a')('b') === fn('a', 'b'); // => true

narynary(fn: function): function

pure function nary :: (a -> b) -> a -> b

nary curried function and allows it to be called both as curried and n-ary.

1
import {nary} from '@7urtle/lambda';
2
3
const fn = nary(a => b => a + b);
4
fn('a')('b') === fn('a', 'b'); // => true

Applicative Functor Monads

Maybe

Applicative Functor Monad

Maybe is one of the simplest and well known monads. Maybe is also quite similar to our monad Either.

Maybe expects a value as its input. It is Nothing if the value is null, undefined, or empty. It returns Just for all other cases.

Maybe is called Maybe because it maybe holds a value. You want to use Maybe for situations when you don't know whether there is going to be an input. For example for your API endpoint, it makes it very obvious that you service may not receive a value by mistake and forces the consumer of Maybe to safely deal with it.

In other languages, Maybe monad can also be called Option monad or Nullable monad.

1
import {maybe, Maybe, Just, Nothing, upperCaseOf, liftA2, flatMap, compose, startsWith} from '@7urtle/lambda';
2
3
// in the example we randomly give Maybe a value or undefined. Maybe.of() outputs an instance of Maybe.
4
const myMaybe = Maybe.of(Math.random() > 0.5 ? 'random success' : undefined);
5
6
// you can use Just and Nothing directly
7
Just('7urtle') === Maybe.of('7urtle'); // => true
8
Just('7urte') === Maybe.Just('7urtle'); // => true
9
Nothing === Maybe.of(undefined); // => true
10
Nothing === Maybe.Nothing; // => true
11
12
// you could access the actual value like this
13
myMaybe.value; // => 'random success' or undefined
14
15
// you can also inspect it by
16
myMaybe.inspect(); // => "Just('random success')" or "Nothing"
17
18
// you can check if the value is Nothing
19
myMaybe.isNothing(); // => true or false
20
Maybe.of('abc').isNothing(); // => false
21
Maybe.of([]).isNothing(); // => true
22
Just('7urtle').isNothing(); // => false
23
Nothing.isNothing(); // => true
24
25
// you can check if the value is Just
26
myMaybe.isJust(); // => true or false
27
Maybe.of(123).isJust(); // => true
28
Maybe.of(null).isJust(); // => false
29
Just('7urtle').isJust(); // => true
30
Nothing.isJust(); // => false
31
32
// as a functor the value inside is safely mappable (map doesn't execute over Nothing)
33
myMaybe.map(value => upperCaseOf(value));
34
myMaybe.inspect(); // => "Just('RANDOM SUCCESS')" or "Nothing"
35
36
// as a monad Maybe can be safely flat mapped with other Maybes (flatMap doesn't execute over Nothing)
37
Maybe.of(3).flatMap(a => Maybe.of(a + 2)).inspect(); // => 'Just(5)'
38
Maybe.of(3).flatMap(a => Maybe.of(null)).inspect(); // => 'Nothing'
39
Maybe.of(3).flatMap(a => a + 2); // => 5
40
41
// as an applicative functor you can apply Maybes to each other especially using liftA2 or liftA3
42
const add = a => b => a + b;
43
liftA2(add)(Maybe.of(2))(Maybe.of(3)); // => Just(5)
44
Maybe.of(1).map(add).ap(Maybe.of(2)).inspect(); // => 'Just(3)'
45
Maybe.of(1).map(add).ap(Maybe.of(null)).inspect(); // => 'Nothing'
46
Maybe.of(add).ap(Maybe.of(1)).ap(Maybe.of(2)).inspect(); // => 'Just(3)'
47
48
// as an example you can use Maybe to help you work with DOM like this
49
Maybe.of(document.querySelector('#iexist')).map(a => a.offsetTop); // => Just(1240)
50
Maybe.of(document.querySelector('#idontexist')).map(a => a.offsetTop); // => Nothing
51
maybe
52
(() => 'error: the object doesnt exist')
53
(offsetTop => 'offset from top is ' + offsetTop)
54
(Maybe.of(document?.querySelector('#iexist')?.offsetTop));
55
56
// to read API request you can use Maybe this way
57
const getQuery = body =>
58
flatMap
59
(a => Maybe.of(a.queryText))
60
(Maybe.of(body.queryResult));
61
62
// you can use Maybe, Just, and Nothing as output of your functions
63
const maybeGetEnvironmentVariable = key => Maybe.of(process?.env?[key]);
64
const maybeDIDKeyFromEnvironment =
65
compose(
66
flatMap(did => startsWith('did:key')(did) ? Just(did) : Nothing),
67
maybeGetEnvironmentVariable
68
);

maybemaybe(onNothing: functioon)(onJust: function)(functorMaybe: Maybe): any

pure function maybe :: (a -> b) -> (c -> d) -> Maybe -> e

maybe outputs result of a function onJust if input Maybe is Just or outputs input error if input Maybe is Nothing.

maybe can be called both as a curried unary function or as a standard ternary function.

1
import {maybe, Maybe} from '@7urtle/lambda';
2
3
maybe(() => 'error')(value => value)(Maybe.of('abc')); // => 'abc'
4
maybe(() => 'error')(value => value)(Maybe.of(undefined)); // => 'error'
5
maybe(() => 'error')(() => 'not error)(Maybe.of(undefined)) === Maybe.of(undefined).isNothing() ? 'error' ? 'not error';
6
7
// maybe can be called both as a curried unary function or as a standard ternary function
8
maybe(() => 'error')(value => value)(Maybe.of('abc')) === maybe('error', value => value, Maybe.of('abc'));

maybeToAsyncEffectmaybeToAsyncEffect(maybeMonad: Maybe): AsyncEffect

pure function maybeToAsyncEffect :: Maybe -> AsyncEffect

maybeToAsyncEffect converts any Maybe monad to an AsyncEffect monad with 'Maybe is Nothing.' reject if the Maybe is Nothing.

1
import { maybeToAsyncEffect, Maybe } from '@7urtle/lambda';
2
3
maybeToAsyncEffect(Maybe.of('7urtle')); // resolves to '7urtle'
4
maybeToAsyncEffect(Maybe.of(undefined)); // rejects 'Maybe is Nothing.'

maybeToEithermaybeToEither(maybeMonad: Maybe): Either

pure function maybeToEither :: Maybe -> Either

maybeToEither converts any Maybe monad to an Either monad with 'Maybe is Nothing.' Failure if the Maybe is Nothing.

1
import { maybeToEither, Maybe } from '@7urtle/lambda';
2
3
maybeToEither(Maybe.of('7urtle')); // => Success('7urtle')
4
maybeToEither(Maybe.of(undefined)); // => Failure('Maybe is Nothing.')

maybeToSyncEffectmaybeToSyncEffect(maybeMonad: Maybe): SyncEffect

pure function maybeToSyncEffect :: Maybe -> SyncEffect

maybeToSyncEffect converts any Maybe monad to an SyncEffect monad with 'Maybe is Nothing.' thrown error if the Maybe is Nothing.

1
import { maybeToSyncEffect, Maybe } from '@7urtle/lambda';
2
3
maybeToSyncEffect(Maybe.of('7urtle')).trigger(); // => '7urtle'
4
maybeToSyncEffect(Maybe.of(undefined)).trigger(); // throws 'Maybe is Nothing.'

mergeMaybesmergeMaybes(maybes: Maybe): Maybe

pure function mergeMaybes :: ([Maybe]) -> Maybe

mergeMaybes outputs Maybe of array with all Maybe values depending whether they are Nothing or Just.

1
import { mergeMaybes, Nothing, Just, Maybe } from '@7urtle/lambda';
2
3
mergeMaybes(Maybe.of('abc'), Just('def')); // => Just(['abc', 'def'])
4
mergeMaybes(Maybe.of('abc'), Nothing); // => Nothing
5
mergeMaybes(Nothing, Maybe.of('def')); // => Nothing
6
mergeMaybes(Nothing, Nothing); // => Nothing

Either

Applicative Functor Monad

Either is an excellent monad for handling error states and it is fairly similar to our monad Maybe. Either.Failure represents an error state and Either.Success represents a success state.

Either.of expects a value as its input. Either.of is the same as Either.Success. You can initiate Either in its error state by Either.Failure.

You can also initiate it using Either.try which expects a function as an input. It is Failure if an error or exception is thrown. It is Success if there are no errors or exceptions.

Either is called Either because it allows you to branch based on an error state. You want to use Either for situations when you don't know whether there might be an error. It makes the very visible that an error can occur and it forces the consumer to handle the situation.

1
import {either, Either, Success, Failure, upperCaseOf, liftA2} from '@7urtle/lambda';
2
3
// in the example we randomly give Either a value or throw an error. Either.try() outputs an instance of Either.
4
const myEither = Either.try(() => Math.random() > 0.5 ? 'random success' : throw 'random failure');
5
6
// you can also return Either.Failure or Either.Success based on a function logic
7
const myFunction = Math.random() > 0.5 ? Either.Success('random success') : Either.Failure('random failure');
8
9
// Success and Failure can be called directly
10
Success('7urtle') === Either.Success('7urtle'); // => true
11
Success('7urtle') === Either.of('7urtle'); // => true
12
Failure('error') === Either.Failure('error'); // => true
13
14
// you could access the actual value like this
15
myEither.value; // => 'random success' or 'random failure'
16
17
// you can also inspect it by
18
myEither.inspect(); // => "Success('random success')" or Failure('random failure')
19
20
// Either.of and Either.Success both represent success states
21
Either.of('some value').inspect() === Success('some value').inspect(); // => true
22
23
// you can check if the value is Failure
24
myEither.isFailure(); // => true or false
25
Either.of('abc').isFailure(); // => false
26
Success('anything').isFailure(); // => false
27
Failure('anything').isFailure(); // => true
28
Either.try(() => {throw 'error'}).isFailure(); // => true
29
30
// you can check if the value is Success
31
myEither.isSuccess(); // => true or false
32
Either.of('abc').isSuccess(); // => true
33
Success('anything').isSuccess(); // => true
34
Failure('anything').isSuccess(); // => false
35
Either.try(() => {throw 'error'}).isSuccess(); // => false
36
37
// as a functor the value inside is safely mappable (map doesn't execute over Failure)
38
myEither.map(value => upperCaseOf(value));
39
myEither.inspect(); // => "Success('RANDOM SUCCESS')" or "Failure('random failure')"
40
41
// as a monad Either can be safely flat mapped with other Eithers (flatMap doesn't execute over Failure)
42
Either.of(3).flatMap(a => Either.of(a + 2)).inspect(); // => 'Success(5)'
43
Failure(3).flatMap(a => Either.of(null)).inspect(); // => 'Failure(3)'
44
Either.of(3).flatMap(a => a + 2); // => 5
45
46
// you can use catchMap if you want to map over Failure
47
Failure('error').catchMap(a => a + 's'); // => Failure('errors')
48
Success('7urtle').catchMap(a => a + 's'); // => Success('7urtle')
49
50
// you can use bimap to map over both Success and Failure with different functions
51
Failure('error').bimap(a + ' is left')(a => a + ' is right'); // => Failure('error is left')
52
Succcess('7urtle').bimap(a + ' is left')(a => a + ' is right'); // => Success('7urtle is right')
53
54
// orOf(a) replaces Failure with Success
55
Failure('error').orOf('7urtles'); // => Success('7urtle')
56
Success('7urtle').orOf('tortoise'); // => Success('7urtle')
57
58
// orElse(a -> Either) replaces Failure with the output of orElse function
59
Failure('error').orElse(() => Success('7urtle')); // => Success('7urtle')
60
Success('7urtle').orElse(() => Success('tortoise')); // => Success('7urtle')
61
62
// orTry(a -> b) replaces original Fairlure with Either.try
63
Failure('error').orTry(() => { throw 'i am an error'; }); // => Failure('i am an error')
64
Failure('error').orTry(() => '7urtle'); // => Success('7urtle')
65
Success('7urtle').orTry(() => { throw 'i am an error'; }); // => Success('7urtle')
66
67
// as an applicative functor you can apply Eithers to each other especially using liftA2 or liftA3
68
const add = a => b => a + b;
69
liftA2(add)(Either.of(2))(Either.of(3)); // => Success(5)
70
Either.of(1).map(add).ap(Either.of(2)).inspect(); // => 'Success(3)'
71
Failure(1).map(add).ap(Either.of(2)).inspect(); // => 'Failure(1)'
72
Either.of(add).ap(Either.of(1)).ap(Either.of(2)).inspect(); // => 'Success(3)'

eithereither(onFailure: function)(onSuccess: function)(functorEither: Either): any

pure function either :: (a -> b) -> (b -> c) -> Either

either outputs result of a function onRight if input Either is Success or outputs result of a function onLeft if input Either is Failure.

either can be called both as a curried unary function or as a standard ternary function.

1
import {either, Either} from '@7urtle/lambda';
2
3
either(a => 'error ' + a)(a => 'success ' + a)(Either.of('abc')); // => 'success abc'
4
either(a => 'error ' + a)(a => 'success ' + a)(Either.Failure('failure')); // => 'error failure'
5
either(a => 'error ' + a)(a => 'success ' + a)(Either.try(() => throw 'failure')); // => 'error failure'
6
7
// either can be called both as a curried unary function or as a standard ternary function
8
either(a => 'error ' + a)(a => 'success ' + a)(Either.of('abc')) === either(a => 'error ' + a, a => 'success ' + a, Either.of('abc'));

eitherToAsyncEffecteitherToAsyncEffect(eitherMonad: Either): AsyncEffect

pure function eitherToAsyncEffect :: Either -> AsyncEffect

eitherToAsyncEffect converts any Either monad to a AsyncEffect monad with rejected error if Either is Failure.

1
import { eitherToAsyncEffect, Either } from '@7urtle/lambda';
2
3
eitherToAsyncEffect(Either.Success('7urtle')); // resolves to '7urtle'
4
eitherToAsyncEffect(Either.Failure('I am an error.')); // rejects 'I am an error.'

eitherToMaybeeitherToMaybe(eitherMonad: Either): Maybe

pure function eitherToMaybe :: Either -> Maybe

eitherToMaybe converts any Either monad to a Maybe monad with Maybe Nothing if Either is Failure.

1
import { eitherToMaybe, Either } from '@7urtle/lambda';
2
3
eitherToMaybe(Either.Success('7urtle')); // => Just('7urtle')
4
eitherToMaybe(Either.Success(undefined)); // => Nothing
5
eitherToMaybe(Either.Failure('I am an error.')); // => Nothing
6
eitherToMaybe(Either.Failure('I am an error.')).value; // => 'I am an error.'

eitherToSyncEffecteitherToSyncEffect(eitherMonad: Either): SyncEffect

pure function eitherToSyncEffect :: Either -> SyncEffect

eitherToSyncEffect converts any Either monad to a SyncEffect monad with error thrown on trigger if Either is Failure.

1
import { eitherToSyncEffect, Either } from '@7urtle/lambda';
2
3
eitherToSyncEffect(Either.Success('7urtle')).trigger(); // => '7urtle'
4
eitherToSyncEffect(Either.Failure('I am an error.')).trigger(); // throws 'I am an error.'

mergeEithersmergeEithers(eithers: Either): Either

pure function mergeEithers :: ([Either]) -> Either

mergeEithers outputs Either of array with all Either values depending whether they are Success or Failure.

1
import { mergeEithers, Either } from '@7urtle/lambda';
2
3
mergeEithers(Either.of('abc'), Either.of('def')); // => Success(['abc', 'def'])
4
mergeEithers(Either.of('abc'), Either.Failure('def')); // => Failure(['def'])
5
mergeEithers(Either.Failure('abc'), Either.of('def')); // => Failure(['abc'])
6
mergeEithers(Either.Failure('abc'), Either.Failure('def')); // => Failure(['abc', 'def'])

validateEithersvalidateEithers(fns: functions)(input: any): Either

pure function validateEithers :: ([a -> b]) -> a -> Either

validateEithers outputs Either of input value if all input functions returns Success or Failure with array of error messages.

1
import { validateEithers, Either, isAtLeast, lengthOf } from '@7urtle/lambda';
2
3
// mergeEithers is great to be used for validations
4
const isPasswordLongEnough = password =>
5
isAtLeast(6)(lengthOf(password))
6
? Either.Success(password)
7
: Either.Failure('Password must have more than 6 characters.');
8
9
const isPasswordStrongEnough = password =>
10
/[\W]/.test(password)
11
? Either.Success(password)
12
: Either.Failure('Password must contain special characters.');
13
14
const validatePassword = validateEithers(isPasswordLongEnough, isPasswordStrongEnough);
15
16
validatePassword('LongPa$$word'); // => Success('LongPa$$word')
17
validatePassword('Pa$$'); // => Failure(['Password must have more than 6 characters.'])
18
validatePassword('LongPassword'); // => Failure(['Password must contain special characters.'])
19
validatePassword('Pass'); // => Failure(['Password must have more than 6 characters.', 'Password must contain special characters.'])

Case

Applicative Functor Monad

Case is a monad that helps you with conditional processing.

Case expects an array of key-value pairs as its input. Case.match then matches against a key to provide its value.

Case is internally build on a JavaScript map and turns it into an applicative functor monad.

1
import {Case, upperCaseOf, liftA2} from '@7urtle/lambda';
2
3
// in the example we define Case using key-value pairs. Case.of() outputs an instance of Case.
4
const myCase = Case.of([[1, 'one'], ['key', 'value'], ['_', 'fallback']]);
5
6
// you reach a value by matching keys using Case.match
7
myCase.match(1); // => 'one'
8
myCase.match('key'); // => 'value'
9
myCase.match('nope'); // => 'fallback'
10
11
// if no fallback is defined and no key is matched, we return undefined
12
Case.of([]).match('nope'); // => undefined
13
14
// you can also inspect it by
15
myCase.inspect(); // => 'Case(...
16
17
// as a functor the result is safely mappable (map doesn't execute over undefined matches)
18
myCase.map(value => upperCaseOf(value)).match('key'); // => 'VALUE'
19
Case.of([]).map(upperCaseOf).match('key'); // => undefined
20
21
// as a monad Case can be safely flat mapped with other Cases (flatMap doesn't execute over undefined)
22
Case.of([[1, 'I am']]).flatMap(a => Case.of([[1, a + ' a turtle']]).match(1); // => 'I am a turtle'
23
Case.of([[1, 'I am']]).flatMap(a => Case.of([])).match(1); // => undefined
24
25
// as an applicative functor you can apply Cases to each other especially using liftA2 or liftA3
26
const add = a => b => a + b;
27
liftA2(add)(Case.of([[1, 1]]))(Case.of([[1, 2]])).match(1); // => 3
28
Case.of([[1, add]]).ap(Case.of([[1, 'I am']])).ap(Case.of([[1, ' a turtle']])).match(1); // => 'I am a turtle'
29
Case.of([[1, add]]).ap(Case.of([])).ap(Case.of([[1, 'I am']])).match(1); // => undefined

SyncEffect

Applicative Functor Monad

SyncEffect is a monad that allows you to safely work with synchronous side effects in JavaScript.

SyncEffect expects as its input a function.

SyncEffect is evaluated lazily and nothing is executed until a trigger function is called. It does not have any inner error/exception handling mechanism for the effects of the trigger. Consider using the monads Maybe and Either for managing the results of the trigger.

In other languages and framework, SyncEffect can be also called the IO monad.

1
import {SyncEffect, log, upperCaseOf, liftA2, Either, isNull} from '@7urtle/lambda';
2
3
// we create SyncEffect that expects a number from 0 to 1
4
// and based on that, it returns a value or throws an error
5
const throwError = () => {throw 'random failure'};
6
const dangerousFunction = value => value > 0.5 ? 'random success' : throwError();
7
const mySyncEffect = SyncEffect.of(dangerousFunction);
8
9
// when you are ready, you can call trigger to trigger the side effect
10
// nothing is executed until the trigger is called
11
mySyncEffect.trigger(Math.random());
12
// => returns 'random success' or throws 'random failure' depending on Math.random() value
13
14
// you can inspect SyncEffect by
15
mySyncEffect.inspect(); // => "SyncEffect(function...
16
17
// as a functor the value inside is safely mappable
18
// map doesn't execute in case of an error and nothing executes until a trigger is called
19
mySyncEffect
20
.map(value => upperCaseOf(value))
21
.trigger(Math.random());
22
// => returns 'RANDOM SUCCESS' or throws 'random failure' depending on Math.random() value
23
24
// as a monad SyncEffect can be safely flat mapped with other SyncEffects
25
// flatMap doesn't execute in case of an error and nothing executes until a trigger is called
26
SyncEffect.of(() => '7turtle').flatMap(a => SyncEffect.of(() => a + 's')).trigger();
27
// => '7urtles'
28
SyncEffect.of(() => {throw 'error'}).flatMap(a => SyncEffect.of(() => a + 's')).trigger();
29
// => throws 'error'
30
31
// as an applicative functor you can apply SyncEffects to each other especially using liftA2 or liftA3
32
const add = a => b => a + b;
33
liftA2(add)(SyncEffect.of(() => 1)(SyncEffect.of(() => 2)).trigger(); // => 3
34
SyncEffect.of(() => add).ap(SyncEffect.of(() => 1)).ap(SyncEffect.of(() => 2)).trigger(); // => 3
35
36
// in practice you can use SyncEffect to work for example with DOM
37
const DOMSyncEffect = SyncEffect.of(targetID => document.querySelector(targetID));
38
const TopOffsetSyncEffect = DOMSyncEffect.map(a => a.offsetTop);
39
const ClientHeightSyncEffect = DOMSyncEffect.map(a => a.clientHeight);
40
41
TopOffsetSyncEffect.trigger('article'); // 1280
42
Either.try(ClientHeightSyncEffect.trigger('#dontexist')); // Failure('Uncaught TypeError: Cannot read property 'offsetTop' of null')

syncEffectToAsyncEffectsyncEffectToAsyncEffect(syncEffectMonad: SyncEffect): AsyncEffect

pure function syncEffectToAsyncEffect :: SyncEffect -> AsyncEffect

syncEffectToAsyncEffect converts any SyncEffect monad to a AsyncEffect monad with AsyncEffect rejecting thrown error.

1
import { syncEffectToAsyncEffect, SyncEffect } from '@7urtle/lambda';
2
3
syncEffectToAsyncEffect(SyncEffect.of(() => '7urtle')); // resolves to '7urtle'
4
syncEffectToAsyncEffect(SyncEffect.of(() => { throw 'I am an error.'; })); // rejects 'I am an error.'

syncEffectToEithersyncEffectToEither(syncEffectMonad: SyncEffect): Either

pure function syncEffectToEither :: SyncEffect -> Either

syncEffectToEither converts any SyncEffect monad to an Either monad with Either Failure containing SyncEffect thrown error.

1
import { syncEffectToEither, SyncEffect } from '@7urtle/lambda';
2
3
syncEffectToEither(SyncEffect.of(() => '7urtle')); // => Success('7urtle')
4
syncEffectToEither(SyncEffect.of(() => { throw 'I am an error.'; })); // => Failure('I am an error.')

syncEffectToMaybesyncEffectToMaybe(syncEffectMonad: SyncEffect): Maybe

pure function syncEffectToMaybe :: SyncEffect -> Maybe

syncEffectToMaybe converts any SyncEffect monad to a Maybe monad with Maybe Nothing if SyncEffect throws an error.

1
import { syncEffectToMaybe, SyncEffect } from '@7urtle/lambda';
2
3
eitherToMaybe(SyncEffect.of(() => '7urtle')); // => Just('7urtle')
4
eitherToMaybe(SyncEffect.of(() => undefined)); // => Nothing
5
eitherToMaybe(SyncEffect.of(() => { throw 'I am an error.'; }))); // => Nothing

AsyncEffect

Applicative Functor Monad

AsyncEffect is a monad that allows you to safely work with asynchronous side effects in JavaScript.

AsyncEffect expects as its input a function that takes two inputs of a reject function, and a resolve function. Reject function is called on failure and resolve function is called on success. It is similar to using JavaScript Promise and AsyncEffect can be directly created from a Promise turning it into a monad.

AsyncEffect is evaluated lazily and nothing is executed until a trigger function is called.

AsyncEffect can also be called Future monad in other libraries or languages.

1
import {AsyncEffect, log, upperCaseOf, liftA2, liftA3} from '@7urtle/lambda';
2
3
// we create AsyncEffect that expects a number from 0 to 1
4
// and based on that, it resolve or rejects 10 milliseconds after it is triggered
5
const myAsyncEffect = AsyncEffect
6
.of(reject => resolve =>
7
setTimeout(() => Math.random() > 0.5 ? resolve('random success') : reject('random failure'), 10)
8
);
9
10
// we could also create AsyncEffect from a function returning JavaScript Promise
11
const myPromise = () => new Promise((resolve, reject) =>
12
setTimeout(() => Math.random() > 0.5 ? resolve('random success') : reject('random failure'), 10)
13
);
14
const promiseAsyncEffect = AsyncEffect.ofPromise(myPromise);
15
16
// you can inspect AsyncEffect by
17
myAsyncEffect.inspect(); // => "AsyncEffect(function...
18
19
// when you are ready, you can call trigger to trigger the side effect
20
// nothing is executed until the trigger is called
21
myAsyncEffect
22
.trigger
23
(error => log(error))
24
(result => log(result));
25
// => logs 'random success' or 'random failure' depending on Math.random() value
26
27
// you can also turn AsyncEffect into a JavaScript Promise
28
myAsyncEffect
29
.promise()
30
.then(result => log(result), error => log(error));
31
// => logs 'random success' or 'random failure' depending on Math.random() value
32
33
// thrown exceptions lead AsyncEffect to reject
34
AsyncEffect
35
.of(() => {
36
throw 'error';
37
})
38
.trigger(log)(log);
39
// => logs 'error'
40
41
// as a functor the value inside is safely mappable
42
// map doesn't execute in case of an error and nothing executes until a trigger is called
43
myAsyncEffect
44
.map(value => upperCaseOf(value))
45
.trigger(log)(log);
46
// => logs 'RANDOM SUCCESS' or 'random failure' depending on Math.random() value
47
48
// as a monad AsyncEffect can be safely flat mapped with other AsyncEffects
49
// flatMap doesn't execute in case of an error and nothing executes until a trigger is called
50
AsyncEffect
51
.of(reject => resolve => resolve('7urtle'))
52
.flatMap(a => AsyncEffect.of(reject => resolve => resolve(a + 's')))
53
.trigger(log)(log);
54
// => logs '7urtles'
55
56
// as an applicative functor you can apply AsyncEffects to each other especially using liftA2 or liftA3
57
const add = a => b => a + b;
58
const AS1 = AsyncEffect.of(reject => resolve => resolve(1));
59
const AS2 = AsyncEffect.of(reject => resolve => resolve(2));
60
liftA2(add)(AS1)(AS2); // => resolve(3)
61
62
const ASFail = AsyncEffect.of(() => {throw 'error'});
63
liftA3(add)(ASFail)(AS1)(AS2); // => reject('error')
64
65
// AsyncEffect.of as well as AsyncEffect.trigger accept both curried and binary functions
66
AsyncEffect.of((reject, resolve) => resolve('7urtle')).trigger(log, log); // logs '7urtle'
67
68
// as an example you can use AsyncEffect to help you work with axios or fs
69
70
// axios example
71
import axios from 'axios';
72
const getFromURL = url => AsyncEffect.ofPromise(() => axios.get(url));
73
74
getFromURL('/my/ajax/url')
75
.trigger
76
(error => log(error))
77
(result => log(result.data));
78
79
// reading file example
80
import fs from 'fs';
81
const readFile => input =>
82
AsyncEffect
83
.of(reject => resolve =>
84
fs.readFile(input, (err, data) =>
85
err ? reject(err) : resolve(data)
86
)
87
);
88
89
readFile('./file.txt')
90
.trigger
91
(error => log(error))
92
(result => log(result));;

mergeAsyncEffectsmergeAsyncEffects(asyncEffects: AsyncEffect): AsyncEffect

pure function mergeAsyncEffects :: ([AsyncEffect]) -> AsyncEffect

mergeAsyncEffects outputs AsyncEffect which resolves with array of all input AsyncEffects or rejects with the first effect rejected.

1
import { mergeAsyncEffects, AsyncEffect } from '@7urtle/lambda';
2
3
const resolvingOne = AsyncEffect.of(_ => resolve => resolve('Resolving One'));
4
const resolvingTwo = AsyncEffect.of(_ => resolve => resolve('Resolving Two'));
5
6
mergeAsyncEffects(resolvingOne, resolvingTwo)
7
.trigger(console.log)(console.log);
8
// => logs ['Resolving One', 'Resolving Two']
9
10
const rejectingOne = AsyncEffect.of(reject => _ => reject('Rejecting One'));
11
const rejectingTwo = AsyncEffect.of(reject => _ => reject('Rejecting Two'));
12
13
mergeAsyncEffects(resolvingOne, rejectingOne, rejectingTwo, resolvingTwo)
14
.trigger(console.log)(console.log);
15
// => logs 'Rejecting One'

List Functions

entriesOfentriesOf(list: Object|array): array

pure function entriesOf :: object -> [[string, a]]

entriesOf outputs array of arrays of string keys and raw values of input array or object.

1
import {entriesOf} from '@7urtle/lambda';
2
3
entriesOf([2, 3, 4]); // => [['0', 2], ['1', 3], ['2', 4]]
4
entriesOf({1: 2, 2: 3}); // => [['1', 2],['2', 3]]

everyOfeveryOf(checker: function)(list: array): boolean

pure function everyOf :: (a -> boolean) -> [a] -> boolean

everyOf outputs true if every element of input array passes input checker function as true.

everyOf can be called both as a curried unary function or as a standard binary function.

1
import {everyOf} from '@7urtle/lambda';
2
3
everyOf(a => a > 1)([2, 3, 4]); // => true
4
everyOf(a => a > 5)([2, 3, 4]); // => false
5
6
// everyOf can be called both as a curried unary function or as a standard binary function
7
everyOf(a => a > 1)([2, 3, 4]) === everyOf(a => a > 1, [2, 3, 4]);

filterfilter(checker: function)(list: array): any

pure function filter :: (a -> boolean) -> [a] -> [b]

filter executes input checker over each member of input array [a] to filter and output filtered new array [b].

If you need to both filter and map over an array, consider using the filterMap function.

filter can be called both as a curried unary function or as a standard binary function.

1
import {filter} from '@7urtle/lambda';
2
3
const list = [0, 1, 2, 3]
4
5
filter(a => a > 1)(list); // => [2, 3]
6
7
// filter can be called both as a curried unary function or as a standard binary function
8
filter(a => a > 1)(list) === filter(a => a > 1, list);

filterMapfilterMap(checker: function)(mapper: function)(list: array): any

pure function filterMap :: (a -> boolean) -> (a -> b) -> [a] -> [b]

filterMap executes mapper function over filtered input array or monad and outputs the resulting array or monad.

Only one pass through the array is executed unlike the use of map(mapper)(filter(checker)(list)).

filterMap can be called both as a curried unary function or as a standard ternary function.

1
import {filterMap} from '@7urtle/lambda';
2
3
const list = [0, 1, 2, 3]
4
const mapper = a => a + 1;
5
const checker = a => a > 1;
6
7
filterMap(checker)(mapper)(list); // => [3, 4]
8
filterMap(a => a > 1)(a => a + 1)([0, 1, 2, 3]); // => [3, 4]
9
10
const mapOverLargerThanOne = filterMap(checker);
11
mapOverLargerThanOne(mapper)(list); // => [3, 4]
12
13
// filterMap can be called both as a curried unary function or as a standard ternary function
14
filterMap(a => a > 1)(a => a + 1)(list) === filterMap(a => a > 1, a => a + 1, list);

findfind(checker: function)(list: array): any

pure function find :: (a -> boolean) -> [a] -> [b]

find executes input checker over each member of input array [a] and outputs the first array member that matches checker or undefined.

find can be called both as a curried unary function or as a standard binary function.

1
import {find} from '@7urtle/lambda';
2
3
const list = [0, 1, 2, 3]
4
5
find(a => a > 1)(list); // => 2
6
find(a => a > 3)(list); // => undefined
7
8
// find can be called both as a curried unary function or as a standard binary function
9
find(a => a > 1)(list) === find(a => a > 1, list);

findIndexfindIndex(checker: function)(list: array): any

pure function findIndex :: (a -> boolean) -> [a] -> [b]

findIndex executes input checker over each member of input array [a] and outputs the index of first array member that matches checker or undefined.

findIndex can be called both as a curried unary function or as a standard binary function.

1
import {findIndex} from '@7urtle/lambda';
2
3
const list = [2, 3, 4];
4
5
findIndex(a => a > 2)(list); // => 1
6
findIndex(a => a > 4)(list); // => undefined
7
8
// findIndex can be called both as a curried unary function or as a standard binary function
9
findIndex(a => a > 1)(list) === findIndex(a => a > 1, list);

groupBygroupBy(fn: function)(list: array): object

pure function groupBy :: (a -> b) -> [a] -> {b: a}

groupBy outputs an objects with groups produced by an input function over input list.

groupBy can be called both as a curried unary function or as a standard binary function.

1
import {groupBy} from '@7urtle/lambda';
2
3
groupBy(a => a.length)(['one', 'two', 'three']);
4
// => {"3": ["one", "two"], "5": ["three"]}
5
6
groupBy(a => a % 2)([1, 2, 3]);
7
// => {"0": [2], "1": [1, 3]}
8
9
// groupBy can be called both as a curried unary function or as a standard binary function
10
groupBy(a => a.length)(['one', 'two', 'three']) === groupBy(a => a.length, ['one', 'two', 'three'])

headOfheadOf(list: array): any

pure function headOf :: [a] -> a

headOf outputs the first item (head) from the input array.

1
import {headOf} from '@7urtle/lambda';
2
3
headOf([3, 4, 1, 8]); // => 3
4
headOf([8]); // => 8
5
headOf([]); // => undefined

initOfinitOf(list: array): array

pure function initOf :: [a] -> []

initOf outputs the the input array without its last item.

1
import {initOf} from '@7urtle/lambda';
2
3
initOf([3, 4, 1, 8]); // => [3, 4, 1]
4
initOf([8]); // => []
5
initOf([]); // => []

joinjoin(separator: string)(list: array): any

pure function join :: string -> [a] -> string

join outputs a string created by joining input array members with input separator.

join can be called both as a curried unary function or as a standard binary function.

1
import {join} from '@7urtle/lambda';
2
3
const list = [2, 3, 4];
4
5
join('')(list); // => '234'
6
join(' and ')(list); // => '2 and 3 and 4'
7
join()(list); // => '2,3,4'
8
9
// join can be called both as a curried unary function or as a standard binary function
10
join('')(list) === join('', list);

keysOfkeysOf(list: Object|array): array

pure function keysOf :: object -> [string]

keysOf outputs array of string keys of input array or object.

1
import {keysOf} from '@7urtle/lambda';
2
3
keysOf([2, 3, 4]); // => ['0', '1', '2']
4
keysOf({1: 2, 2: 3}); // => ['1', '2']

lastOflastOf(list: array): any

pure function lastOf :: [a] -> a

lastOf outputs the last item from the input array.

1
import {lastOf} from '@7urtle/lambda';
2
3
lastOf([3, 4, 1, 8]); // => 8
4
lastOf([3]); // => 3
5
lastOf([]); // => undefined

randomOfrandomOf(list: array): any

pure function randomOf :: [a] -> a

randomOf outputs a random item from the input array.

1
import {randomOf} from '@7urtle/lambda';
2
3
randomOf([3, 4, 1, 8]); // => 8
4
randomOf([3]); // => 3
5
randomOf([]); // => undefined

reducereduce(initial: any)(reducer: function)(list: array): any

pure function reduce :: a -> ((a, b) -> a) -> [b] -> a

reduce executes input reducer function that over each member of input array [b] to output a single value. It is the preferred way of working functionally with arrays as it is a pure function that does not cause mutations.

reduce executes functions in reverse order to reduceRight.

reduce can be called both as a curried unary function or as a standard ternary function.

1
import {reduce} from '@7urtle/lambda';
2
3
const reducer = (accumulator, currentValue) => accumulator + currentValue;
4
const list = ['a', 'b', 'c'];
5
6
reduce('start')(reducer)(list); // => startabc
7
8
// reduce can be called both as a curried unary function or as a standard ternary function
9
reduce('start')(reducer)(list) === reduce('start', reducer, list);

reduceRightreduceRight(initial: any)(reducer: function)(list: array): any

pure function reduceRight :: a -> ((a, b) -> a) -> [b] -> a

reduceRight executes input reducer function that over each member of input array [b] to output a single value. It is the preferred way of working functionally with arrays as it is a pure function that does not cause mutations.

reduceRight executes functions in reverse order to reduce.

reduceRight can be called both as a curried unary function or as a standard ternary function.

1
import {reduceRight} from '@7urtle/lambda';
2
3
const reducer = (accumulator, currentValue) => accumulator + currentValue;
4
const list = ['a', 'b', 'c'];
5
6
reduceRight('start')(reducer)(list); // => startcba
7
8
// reduceRight can be called both as a curried unary function or as a standard ternary function
9
reduceRight('start')(reducer)(list) === reduceRight('start', reducer, list);

sliceslice(end: number)(start: number)(list: array): array

pure function slice :: number -> number -> [a] -> [a]

slice outputs selected array elements as an array based on input range. First argument end represents the ending index (not length) and start represents the starting index in the input array list.

slice can be called both as a curried unary function or as a standard ternary function.

1
import {slice} from '@7urtle/lambda';
2
3
slice(2)(1)([1, 2, 3, 4, 5]); // => [2]
4
slice(2)(0)([1, 2, 3, 4, 5]); // => [1, 2]
5
slice(8)(7)([1, 2, 3, 4, 5]); // => []
6
7
// slice can be called both as a curried unary function or as a standard ternary function
8
slice(2)(1)([1, 2, 3, 4, 5]) === slice(2, 1, [1, 2, 3, 4, 5]);

someOfsomeOf(checker: function)(list: array): boolean

pure function some :: (a -> boolean) -> [a] -> boolean

some outputs true if any element of input array passes input checker function as true.

some can be called both as a curried unary function or as a standard binary function.

1
import {some} from '@7urtle/lambda';
2
3
someOf(a => a > 1)([2, 3, 4]); // => true
4
someOf(a => a > 5)([2, 3, 4]); // => false
5
6
// some can be called both as a curried unary function or as a standard binary function
7
someOf(a => a > 1)([2, 3, 4]) === someOf(a => a > 1, [2, 3, 4]);

sortsort(compare: function)(list: array): array

pure function sort :: (a -> number) -> [a] -> [a]

sort outputs an array sorted based on input compare function.

sort can be called both as a curried unary function or as a standard binary function.

1
import {sort} from '@7urtle/lambda';
2
3
sort((a, b) => a < b ? -1 : a > b ? 1 : 0)(['a', 'd', 'c', 'd']); // => ['a', 'c', 'd', 'd']
4
sort((a, b) => a - b)([5, 3, 6]); // => [3, 5, 6]
5
6
// sort can be called both as a curried unary function or as a standard binary function
7
sort((a, b) => a - b)([5, 3, 6]) === sort((a, b) => a - b, [5, 3, 6]);

sortAlphabeticallysortAlphabetically(list: array): array

pure function sortAlphabetically :: [string] -> [string]

sortAlphabetically outputs an array sorted alphabetically from a to z.

1
import {sortAlphabetically} from '@7urtle/lambda';
2
3
sortAlphabetically(['petra', 'Martin', 'Petra']); // => ['Martin', 'petra', 'Petra']

sortAlphabeticallyZAsortAlphabeticallyZA(list: array): array

pure function sortAlphabeticallyZA :: [string] -> [string]

sortAlphabeticallyZA outputs an array sorted alphabetically from z to a.

1
import {sortAlphabeticallyZA} from '@7urtle/lambda';
2
3
sortAlphabeticallyZA(['petra', 'Martin', 'Petra']); // => ['petra', 'Petra', 'Martin']

sortNumericallysortNumerically(list: array): array

pure function sortNumerically :: [number] -> [number]

sortNumerically outputs an array sorted numerically from 1 to 2.

1
import {sortNumerically} from '@7urtle/lambda';
2
3
sortNumerically([3, 4, 1, 3]); // => [1, 3, 3, 4]

sortNumerically21sortNumerically21(list: array): array

pure function sortNumerically21 :: [number] -> [number]

sortNumerically21 outputs an array sorted numerically from 2 to 1.

1
import {sortNumerically21} from '@7urtle/lambda';
2
3
sortNumerically21([3, 4, 1, 3]); // => [4, 3, 3, 1]

tailOftailOf(list: array): array

pure function tailOf :: [a] -> []

tailOf outputs the the input array without its first item.

1
import {tailOf} from '@7urtle/lambda';
2
3
tailOf([3, 4, 1, 8]); // => [4, 1, 8]
4
tailOf([8]); // => []
5
tailOf([]); // => []

String Functions

endsWithendsWith(substring: string)(string: string): boolean

pure function endsWith :: string -> string -> boolean

endsWith outputs true if an input string ends with provided string.

endsWith can be called both as a curried unary function or as a standard binary function.

1
import {endsWith} from '@7urtle/lambda';
2
3
endsWith('7e')('7urtle'); // => true
4
endsWith('urtle')('7urtle'); // => true
5
endsWith('urtls')('7urtle'); // => false
6
7
// endsWith can be called both as a curried unary function or as a standard binary function
8
endsWith('e')('7urtle') === endsWith('e', '7urtle');

firstLetterOffirstLetterOf(string: string): string

pure function firstLetterOf :: string -> string

firstLetterOf outputs the first letter of a provided string.

1
import {firstLetterOf} from '@7urtle/lambda';
2
3
firstLetterOf('7urtle'); // => '7'

lastLetterOflastLetterOf(string: string): string

pure function lastLetterOf :: string -> string

lastLetterOf outputs the last letter of a provided string.

1
import {lastLetterOf} from '@7urtle/lambda';
2
3
lastLetterOf('7urtle'); // => 'e'

lowerCaseOflowerCaseOf(string: string): string

pure function lowerCaseOf :: string -> string

lowerCaseOf outputs the lower case version of input string.

1
import {lowerCaseOf} from '@7urtle/lambda';
2
3
lowerCaseOf('PeTrA'); // => 'petra'
4
lowerCaseOf('PŘÍŠERNĚ ŽLUŤOUČKÝ KŮŇ ÚPĚL ĎÁBELSKÉ ÓDY'); // => 'příšerně žluťoučký kůň úpěl ďábelské ódy'

repeatrepeat(count: number)(string: string): string

pure function repeat :: number -> string -> string

repeat outputs new string repeating input string inputted count of times.

repeat can be called both as a curried unary function or as a standard binary function.

1
import {repeat} from '@7urtle/lambda';
2
3
repeat(2)('7urtle'); // => '7urtle7urtle'
4
repeat(0)('7urtle'); // => ''
5
6
// repeat can be called both as a curried unary function or as a standard binary function
7
repeat(2)('7urtle') === repeat(2, '7urtle');

replacereplace(replacement: string)(substring: string)(string: string): string

pure function replace :: string -> string -> string -> string

replace outputs new string replacing input substring with input replacement string in input string.

replace can be called both as a curried unary function or as a standard ternary function.

1
import {replace} from '@7urtle/lambda';
2
3
replace('8')('7')('7urtle'); // => '8urtle'
4
replace('7')('')('7urtle'); // => '77urtle'
5
replace('')('7')('7urtle'); // => 'urtle'
6
7
// replace can be called both as a curried unary function or as a standard ternary function
8
replace('8')('7')('7urtle') === replace('8', '7', '7urtle');

splitsplit(substring: string)(string: string): array

pure function split :: string -> string -> array

split outputs and array of an input string split by the input substring.

split can be called both as a curried unary function or as a standard binary function.

1
import {split} from '@7urtle/lambda';
2
3
split(' ')('7urtles are awesome'); // => ['7urtles', 'are', 'awesome']
4
split('/')('7urtles are awesome'); // => ['7urtles are awesome']
5
6
// split can be called both as a curried unary function or as a standard binary function
7
split(' ')('7urtles are awesome') === split(' ', '7urtles are awesome');

startsWithstartsWith(substring: string)(string: string): boolean

pure function startsWith :: string -> string -> boolean

startsWith outputs true if an input string starts with provided string.

startsWith can be called both as a curried unary function or as a standard binary function.

1
import {startsWith} from '@7urtle/lambda';
2
3
startsWith('7')('7urtle'); // => true
4
startsWith('7urtl')('7urtle'); // => true
5
startsWith('8urtl')('7urtle'); // => false
6
7
// startsWith can be called both as a curried unary function or as a standard binary function
8
startsWith('7')('7urtle') === startsWith('7', '7urtle');

substrsubstr(limit: number)(start: number)(string: string): string

pure function substr :: number -> number -> string -> string

substr outputs substring based on provided string, start and limit.

substr can be called both as a curried unary function or as a standard ternary function.

1
import {substr} from '@7urtle/lambda';
2
3
substr(3)(1)('7urtle'); // => 'urt'
4
substr(1)(0)('7urtle'); // => '7'
5
substr(1)(-1)('7urtle'); // => 'e'
6
7
// substr can be called both as a curried unary function or as a standard ternary function
8
substr(3)(1)('7urtle') === substr(3, 1, '7urtle');

testRegExtestRegEx(regex: regex)(string: string): boolean

pure function testRegEx :: regex -> string -> boolean

testRegEx outputs true if string b passes regular expression a.

testRegEx can be called both as a curried unary function or as a standard binary function.

1
import {testRegEx} from '@7urtle/lambda';
2
3
testRegEx(/[a-z]/)('7urtle'); // => true
4
testRegEx(/[0-9]/)('1'); // => true
5
testRegEx(/[0-9]/)('abc'); // => false
6
7
// testRegEx can be called both as a curried unary function or as a standard binary function
8
testRegEx(/[a-z]/)('7urtle') === testRegEx(/[a-z]/, '7urtle');

trimtrim(string: string): string

pure function trim :: string -> string

trim output is a string without white characters around it.

1
import {trim} from '@7urtle/lambda';
2
3
trim(' a \n '); // => 'a'

upperCaseOfupperCaseOf(string: string): string

pure function upperCaseOf :: string -> string

upperCaseOf outputs the upper case version of input string.

1
import {upperCaseOf} from '@7urtle/lambda';
2
3
upperCaseOf('PeTrA'); // => 'PETRA'
4
upperCaseOf('příšerně žluťoučký kůň úpěl ďábelské ódy'); // => 'PŘÍŠERNĚ ŽLUŤOUČKÝ KŮŇ ÚPĚL ĎÁBELSKÉ ÓDY'

Conditional Functions

andand(predicates: function)(anything: any): any

pure function and :: [(a -> boolean)] -> a -> boolean

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.

1
import {and, isGreaterThan, isLessThan} from '@7urtle/lambda';
2
3
const isEven = number => number % 2 === 0;
4
5
const isSingleEvenDigit = and(isEven, isGreaterThan(-10), isLessThan(10));
6
isSingleEvenDigit(8)
7
// => true

ifElseifElse(predicate: function)(whenTrueFn: function)(whenFalseFn: function)(anything: any): any

pure function ifElse :: (a -> Boolean) -> (a -> a) -> (a -> a) a -> a

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).

1
import {ifElse} from '@7urtle/lambda';
2
3
const predicate = a => a > 1;
4
const whenTrueFn = a => a / 2;
5
const whenFalseFn = a => a * 2;
6
7
ifElse(predicate)(whenTrueFn)(whenFalseFn)(4); // => 2
8
ifElse(predicate)(whenTrueFn)(whenFalseFn)(1); // => 2
9
10
ifElse(predicate)(whenTrueFn)(whenFalseFn)(1) === ifElse(predicate, whenTrueFn, whenFalseFn, 1); // => true

isArrayisArray(a: any): boolean

pure function isArray :: a -> boolean

isArray output is true if input is an array.

1
import {isArray} from '@7urtle/lambda';
2
3
isArray([]); // => true
4
isArray({}); // => false

isAtLeastisAtLeast(a: number)(b: number): boolean

pure function isAtLeast :: a -> b -> boolean

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.

1
import {isAtLeast} from '@7urtle/lambda';
2
3
isAtLeast(1)(2); // => true
4
isAtLeast(2)(2); // => true
5
isAtLeast(3)(2); // => false
6
7
// isAtLeast can be called both as a curried unary function or as a standard binary function
8
isAtLeast(1)(2) === isAtLeast(1, 2);

isAtMostisAtMost(a: number)(b: number): boolean

pure function isAtMost :: a -> b -> boolean

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.

1
import {isAtMost} from '@7urtle/lambda';
2
3
isAtMost(1)(2); // => false
4
isAtMost(2)(2); // => true
5
isAtMost(3)(2); // => true
6
7
// isAtLeast can be called both as a curried unary function or as a standard binary function
8
isAtMost(3)(2) === isAtMost(31, 2);

isBetweenisBetween(a: number)(b: number)(c: number): boolean

pure function isBetween :: a -> b -> c -> boolean

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.

1
import {isBetween} from '@7urtle/lambda';
2
3
isBetween(1)(3)(2); // => true
4
isBetween(3)(1)(2); // => true
5
isBetween(1)(3)(3); // => false
6
isBetween(1)(3)(4); // => false
7
8
// isBetween can be called both as a curried unary function or as a standard ternary function
9
isBetween(1)(3)(2) === isBetween(1, 3, 2);

isBooleanisBoolean(a: any): boolean

pure function isBoolean :: a -> boolean

isBoolean output is true if input is a boolean.

1
import {isBoolean} from '@7urtle/lambda';
2
3
isBoolean(false); // => true
4
isBoolean(1); // => false

isDeepEqualisDeepEqual(a: any)(b: any): boolean

pure function isDeepEqual :: a -> b -> boolean

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.

1
import {isDeepEqual} from '@7urtle/lambda';
2
3
isDeepEqual('something')('something'); // => true
4
isDeepEqual('something')('something else'); // => false
5
isDeepEqual(['a'])(['a']); // => true
6
isDeepEqual({a : 'something'})({a : 'something'}); // => true
7
isDeepEqual([])([]); // => true
8
isDeepEqual([])([]); // => true
9
10
// isDeepEqual can be called both as a curried unary function or as a standard binary function
11
isDeepEqual('something')('something') === isDeepEqual('something', 'something');

isElementisElement(anything: any): boolean

pure function isElement :: a -> boolean

isElement output is true if input is an HTML or SVG Element. Otherwise it is false.

1
import {isElement} from '@7urtle/lambda';
2
3
isElement(document.createElement('span')); // => true

isEmptyisEmpty(anything: string|array|object): boolean

pure function isEmpty :: (string|array|Element) -> boolean

isEmpty output is true if input is an empty string, array, or object. Otherwise it is false.

1
import {isEmpty} from '@7urtle/lambda';
2
3
isEmpty(''); // => true
4
isEmpty([]); // => true
5
isEmpty({}); // => true
6
isEmpty('abc'); // => false
7
isEmpty(document.getElementByID('image')); // => false

isEqualisEqual(a: any)(b: any): boolean

pure function isEqual :: a -> b -> boolean

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.

1
import {isEqual} from '@7urtle/lambda';
2
3
isEqual('something')('something'); // => true
4
isEqual('something')('something else'); // => false
5
isEqual(['a'])(['a']); // => false
6
isEqual({a : 'something'})({a : 'something'}); // => false
7
isEqual([])([]); // => false
8
isEqual([])([]); // => false
9
10
// isEqual can be called both as a curried unary function or as a standard binary function
11
isEqual('something')('something') === isEqual('something', 'something');

isFalseisFalse(anything: any): boolean

pure function isFalse :: a -> Boolean

isFalse output is true if input is false.

1
import {isFalse} from '@7urtle/lambda';
2
3
isFalse(true); // => false
4
isFalse(false); // => true

isFunctionisFunction(a: any): boolean

pure function isFunction :: a -> boolean

isFunction output is true if input is a function.

1
import {isFunction} from '@7urtle/lambda';
2
3
isFunction(() => null); // => true
4
isFunction(1); // => false

isGreaterThanisGreaterThan(a: number)(b: number): boolean

pure function isGreaterThan :: a -> b -> boolean

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.

1
import {isGreaterThan} from '@7urtle/lambda';
2
3
isGreaterThan(1)(2); // => true
4
isGreaterThan(3)(2); // => false
5
6
// isGreaterThan can be called both as a curried unary function or as a standard binary function
7
isGreaterThan(1)(2) === isGreaterThan(1, 2);

isInRangeisInRange(a: number)(b: number)(c: number): boolean

pure function isInRange :: a -> b -> c -> boolean

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.

1
import {isInRange} from '@7urtle/lambda';
2
3
isInRange(1)(3)(2); // => true
4
isInRange(3)(1)(2); // => true
5
isInRange(1)(3)(3); // => true
6
isInRange(1)(3)(4); // => false
7
8
// isInRange can be called both as a curried unary function or as a standard ternary function
9
isInRange(1)(3)(2) === isInRange(1, 3, 2);

isJustisJust(anything: any): boolean

pure function isJust :: a -> boolean

isJust returns true if input is not null, undefined or empty string or empty array or empty object.

1
import { isJust, Maybe, Just, Nothing } from '@7urtle/lambda';
2
3
isJust(null); // => false
4
isJust(undefined); // => false
5
isJust(''); // => false
6
isJust([]); // => false
7
isJust({}); // => false
8
isJust(Nothing); // => false
9
isJust('7urtle'); // => true
10
isJust(Maybe.of('7urtle')); // => true
11
isJust(Just('7urtle')); // => true

isLengthisLength(a: string|array)(b: number): boolean

pure function isLength :: (string|array) -> b -> boolean

isLength output is true if b is a length of a.

1
import {isLength} from '@7urtle/lambda';
2
3
isLength(3)('abc'); // => true
4
isLength(3)([1,2,3]); // => true
5
isLength(3)('abc'); // => false

isLessThanisLessThan(a: number)(b: number): boolean

pure function isLessThan :: a -> b -> boolean

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.

1
import {isLessThan} from '@7urtle/lambda';
2
3
isLessThan(1)(2); // => false
4
isLessThan(3)(2); // => true
5
6
// isLessThan can be called both as a curried unary function or as a standard binary function
7
isLessThan(3)(2) === isLessThan(3, 2);

isNotArrayisNotArray(a: any): boolean

pure function isNotArray :: a -> boolean

isNotArray output is true if input is not an array.

1
import {isNotArray} from '@7urtle/lambda';
2
3
isNotArray([]); // => false
4
isNotArray({}); // => true

isNotBooleanisNotBoolean(a: any): boolean

pure function isNotBoolean :: a -> boolean

isNotBoolean output is true if input is not a boolean.

1
import {isNotBoolean} from '@7urtle/lambda';
2
3
isNotBoolean(false); // => false
4
isNotBoolean(1); // => true

isNotDeepEqualisNotDeepEqual(a: any)(b: any): boolean

pure function isNotDeepEqual :: a -> b -> boolean

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.

1
import {isNotDeepEqual} from '@7urtle/lambda';
2
3
isNotDeepEqual('something')('something'); // => false
4
isNotDeepEqual('something')('something else'); // => true
5
isNotDeepEqual(['a', 'b'])(['a']); // => true
6
isNotDeepEqual({a : 'something', b: c => c})({a : 'something'}); // => true
7
isNotDeepEqual([])([]); // => false
8
isNotDeepEqual([])([]); // => false
9
10
// isNotDeepEqual can be called both as a curried unary function or as a standard binary function
11
isNotDeepEqual('something')('something else') === isNotDeepEqual('something', 'something else');

isNotElementisNotElement(anything: any): boolean

pure function isNotElement :: a -> boolean

isNotElement output is true if input is not an HTML or SVG Element. Otherwise it is false.

1
import {isNotElement} from '@7urtle/lambda';
2
3
isNotElement(document.createElement('span')); // => false

isNotEmptyisNotEmpty(anything: string|array|object): boolean

pure function isNotEmpty :: (string|array|Element) -> boolean

isNotEmpty output is false if input is an empty string, array, or object. Otherwise it is true.

1
import {isNotEmpty} from '@7urtle/lambda';
2
3
isNotEmpty(''); // => false
4
isNotEmpty([]); // => false
5
isNotEmpty('abc'); // => true
6
isNotEmpty({}); => true
7
isNotEmpty(document.getElementByID('image')); // => true

isNotEqualisNotEqual(a: any)(b: any): boolean

pure function isNotEqual :: a -> b -> boolean

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.

1
import {isNotEqual} from '@7urtle/lambda';
2
3
isNotEqual('something')('something'); // => false
4
isNotEqual('something')('something else'); // => true
5
isNotEqual(['a'])(['a']); // => true
6
isNotEqual({a : 'something'})({a : 'something'}); // => true
7
isNotEqual([])([]); // => true
8
isNotEqual([])([]); // => true
9
10
// isNotEqual can be called both as a curried unary function or as a standard binary function
11
isNotEqual('something')('something else') === isNotEqual('something', 'something else');

isNotFunctionisNotFunction(a: any): boolean

pure function isNotFunction :: a -> boolean

isNotFunction output is true if input is not a function.

1
import {isNotFunction} from '@7urtle/lambda';
2
3
isNotFunction(() => null); // => false
4
isNotFunction(1); // => true

isNothingisNothing(anything: any): boolean

pure function isNothing :: a -> boolean

isNothing returns true if input is null, undefined or empty string or empty array or empty object or the monad Nothing.

1
import { isNothing, Maybe, Just, Nothing } from '@7urtle/lambda';
2
3
isNothing(null); // => true
4
isNothing(undefined); // => true
5
isNothing(''); // => true
6
isNothing([]); // => true
7
isNothing({}); // => true
8
isNothing(Maybe.of('')); // => true
9
isNothing(Nothing); // => true
10
isNothing('7urtle'); // => false
11
isNothing(Maybe.of('7urtle')); // => false
12
isNothing(Just('7urtle')); // => false

isNotLengthisNotLength(a: string|array)(b: number): boolean

pure function isNotLength :: (string|array) -> b -> boolean

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).

1
import {isNotLength} from '@7urtle/lambda';
2
3
isNotLength(3)('abc'); // => false
4
isNotLength(3)([1,2,3]); // => false
5
isNotLength(3)('abce'); // => true
6
7
isNotLength(3)('abcd') === isNotLength(3, 'abcd'); // => true

isNotNullisNotNull(a: any): boolean

pure function isNotNull :: a -> boolean

isNotNull output is true if input is not a null.

1
import {isNotNull} from '@7urtle/lambda';
2
3
isNotNull(null); // => false
4
isNotNull(1); // => true

isNotNumberisNotNumber(a: any): boolean

pure function isNotNumber :: a -> boolean

isNotNumber output is true if input is not a number.

1
import {isNotNumber} from '@7urtle/lambda';
2
3
isNotNumber(1); // => false
4
isNotNumber('string'); // => true

isNotObjectisNotObject(a: any): boolean

pure function isNotObject :: a -> boolean

isNotObject output is true if input is not an object, array, or null.

1
import {isNotObject} from '@7urtle/lambda';
2
3
isNotObject({}); // => false
4
isNotObject([]); // => false
5
isNotObject(null); // => false
6
isNotObject(1); // => true

isNotStringisNotString(a: any): boolean

pure function isNotString :: a -> boolean

isNotString output is true if input is not a string.

1
import {isNotString} from '@7urtle/lambda';
2
3
isNotString('string'); // => false
4
isNotString(1); // => true

isNotTypeOfisNotTypeOf(a: any)(b: any): boolean

pure function isNotTypeOf :: a -> b -> boolean

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.

1
import {isNotTypeOf} from '@7urtle/lambda';
2
3
isNotTypeOf('number')(1); // => false
4
isNotTypeOf('string')(1); // => true
5
6
// isNotTypeOf can be called both as a curried unary function or as a standard binary function
7
isNotTypeOf('string')(1) === isNotTypeOf('string', 1);

isNotUndefinedisNotUndefined(a: any): boolean

pure function isNotUndefined :: a -> boolean

isNotUndefined output is true if input is not an undefined.

1
import {isNotUndefined} from '@7urtle/lambda';
2
3
isNotUndefined(undefined); // => false
4
isNotUndefined(1); // => true

isNotZeroisNotZero(a: number): boolean

pure function isNotZero :: a -> boolean

isNotZero output is true if input is not 0.

1
import {isZero} from '@7urtle/lambda';
2
3
isZero(0); // => false
4
isZero(1); // => true

isNullisNull(a: any): boolean

pure function isNull :: a -> boolean

isNull output is true if input is a null.

1
import {isNull} from '@7urtle/lambda';
2
3
isNull(null); // => true
4
isNull(1); // => false

isNumberisNumber(a: any): boolean

pure function isNumber :: a -> boolean

isNumber output is true if input is a number.

1
import {isNumber} from '@7urtle/lambda';
2
3
isNumber(1); // => true
4
isNumber('string'); // => false

isObjectisObject(a: any): boolean

pure function isObject :: a -> boolean

isObject output is true if b is an object, array, or null.

1
import {isObject} from '@7urtle/lambda';
2
3
isObject({}); // => true
4
isObject([]); // => true
5
isObject(null); // => true
6
isObject(1); // => false

isStringisString(a: any): boolean

pure function isString :: a -> boolean

isString output is true if input is a string.

1
import {isString} from '@7urtle/lambda';
2
3
isString('string'); // => true
4
isString(1); // => false

isTrueisTrue(anything: any): boolean

pure function isTrue :: a -> boolean

isTrue output is true if input is true.

1
import {isTrue} from '@7urtle/lambda';
2
3
isTrue(true); // => true
4
isTrue(false); // => false

isTypeOfisTypeOf(a: any)(b: any): boolean

pure function isTypeOf :: a -> b -> boolean

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.

1
import {isTypeOf} from '@7urtle/lambda';
2
3
isTypeOf('number')(1); // => true
4
isTypeOf('string')(1); // => false
5
6
// isTypeOf can be called both as a curried unary function or as a standard binary function
7
isTypeOf('number')(1) === isTypeOf('number', 1);

isUndefinedisUndefined(a: any): boolean

pure function isUndefined :: a -> boolean

isUndefined output is true if input is an undefined.

1
import {isUndefined} from '@7urtle/lambda';
2
3
isUndefined(undefined); // => true
4
isUndefined(1); // => false

isZeroisZero(a: number): boolean

pure function isZero :: a -> boolean

isZero output is true if input is 0.

1
import {isZero} from '@7urtle/lambda';
2
3
isZero(0); // => true
4
isZero(1); // => false

oror(predicates: function)(anything: any): any

pure function or :: [(a -> boolean)] -> a -> boolean

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.

1
import {or} from '@7urtle/lambda';
2
3
const isDivisibleBy = divisor => number => number % divisor === 0;
4
const isFizzBuzzNumber = or(isDivisibleBy(3), isDivisibleBy(5));
5
6
isFizzBuzzNumber(15)
7
// => true

unlessunless(predicate: function)(whenFalseFn: function)(anything: any): any

pure function unless :: (a -> Boolean) -> (a -> a) -> a -> a

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).

1
import {unless} from '@7urtle/lambda';
2
3
const predicate = a => a > 1;
4
const whenFalseFn = a => a * 2;
5
6
when(predicate)(whenFalseFn)(4); // => 4
7
when(predicate)(whenFalseFn)(1); // => 2
8
9
when(predicate)(whenFalseFn)(1) === when(predicate, whenFalseFn, 1); // => true

whenwhen(predicate: function)(whenTrueFn: function)(anything: any): any

pure function when :: (a -> Boolean) -> (a -> a) -> a -> a

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).

1
import {when} from '@7urtle/lambda';
2
3
const predicate = a => a > 1;
4
const whenTrueFn = a => a * 2;
5
6
when(predicate)(whenTrueFn)(2); // => 4
7
when(predicate)(whenTrueFn)(1); // => 1
8
9
when(predicate)(whenTrueFn)(2) === when(predicate, whenTrueFn, 2); // => true

Get Started

Install @7urtle/lambda with NPM or add it directly to your website.