A collection of JavaScript/TypeScript modules for functional programming
- equals ::
Setoid a => a -> a-> Boolean
ora -> b -> Boolean
- isEqual ::
a -> b -> Boolean
- isSame ::
a -> b -> Boolean
- isSameType ::
a -> b -> Boolean
- isTruthy ::
a -> Boolean
- isNil ::
a -> Boolean
- isFunction ::
a -> Boolean
- isDate ::
a -> Boolean
- isIterable ::
a -> Boolean
- isSetoid ::
a -> Boolean
- inspect ::
a -> String
- nodeInspect ::
Symbol
- random ::
(Number | Undefined) -> Number
identity :: a -> a
I :: a -> a
This is the identity
(I
) combinator. It takes a value and returns the same
value.
import { identity, I } from "eek-whales"
identity(42) // => 42
identity("tacocat") // => "tacocat"
I(42) // => 42
constant :: a -> b -> a
This is the K (Kestrel) combinator. It takes two values and returns the first.
import { constant } from "eek-whales"
constant(42)(73) // => 42
constant("Kestrel")("Identity") // => "Kestrel"
equals :: Setoid a => a -> a -> Boolean
equals :: a -> b -> Boolean
The equals
function is useful for deep equality comparisons or for comparing
two values of the Setoid
type. Returns true
given two values
that are deeply equal and false
otherwise. Primitive values are checked using
the isSame
module. Setoids
are compared using their equals
or
fantasy-land/equals
methods.
import { equals } from "eek-whales"
equals([1, 2, 3])([1, 2, 3]) // => true
equals({ a: 1, b: 2 })({ a: 1, b: 2 }) // => true
equals(NaN)(NaN) // => true
equals([])([]) // => true
equals(0)(-0) // => false
equals([4])([2]) // => false
// `Max` is a Setoid [Object] with an `equals` method
equals(Max(42))(Max(43)) // => false
getType :: a -> String
getType
is a function that returns a value's type, given any value. The
original version of this function was named type
, but was changed to avoid
conflicts with the TypeScript keyword.
import { getType } from "eek-whales"
getType("hello") // => "String"
getType([1, 2, 3]) // => "Array"
getType(42) // => "Number"
getType(/^foo$/i) // => "RegExp"
getType(<T>(x: T): T => x) // => "Function"
// An object with a custom type
const MyCustomType = {
"@@type": "CustomType",
}
// An object with a custom type using the Symbol.toStringTag
const AnotherCustomType = {
get [Symbol.toStringTag]() {
return "CustomType"
},
}
getType(MyCustomType) // => "CustomType"
getType(AnotherCustomType) // => "CustomType"
is :: String -> a -> Boolean
The is
function accepts two parameters. The first is a string that represents
the type for the second parameter to be validated against. Uses
getType
on the second parameter for the comparison.
import { is } from "eek-whales"
is("String")("hello") // => true
is("String")(42) // => false
is("Array")([1, 2, 3]) // => true
is("Array")({ a: 1 }) // => false
is("Undefined")() // => true
is("Max")(Max(42).concat(Max(41))) // => true
isEqual :: a -> b -> Boolean
The isEqual
predicate function compares two values using the strict equality
(===
) comparison operator with the exception of NaN
which returns true
when compared with NaN
.
import { isEqual } from "eek-whales"
isEqual("pizza")("pizza") // => true
isEqual(42)(42) // => true
isEqual(NaN)(NaN) // => true
isEqual({})({}) // => false
isEqual([6])([6]) // => false
isEqual("night")("day") // => false
isSame :: a -> b -> Boolean
The isSame
predicate function is similar to isEqual with the
exception of negative zero (-0
) and zero (0
, +0
) not being equal. It is
equivalent to the JavaScript Object.is
static method.
import { isSame } from "eek-whales"
isSame(0)(0) // => true
isSame(0)(+0) // => true
isSame(0)(-0) // => false
isSame(-0)(+0) // => false
isSameType :: a -> b -> Boolean
isSameType
accepts any value for both parameters and returns a boolean that
represents if both parameters are of the same type.
import { isSameType } from "eek-whales"
isSameType("hello")("world") // => true
isSameType(21)(42) // => true
isSameType(null)(undefined) // => false
isSameType({})([]) // => false
isTruthy :: a -> Boolean
isTruthy
returns the result of converting the given parameter into a boolean.
import { isTruthy } from "eek-whales"
isTruthy(true) // => true
isTruthy({}) // => true
isTruthy([]) // => true
isTruthy(42) // => true
isTruthy("0") // => true
isTruthy(new Date()) // => true
isTruthy(Infinity) // => true
isTruthy(false) // => false
isTruthy(0) // => false
isTruthy(-0) // => false
isTruthy(0n) // => false
isTruthy("") // => false
isTruthy(null) // => false
isTruthy(undefined) // => false
isTruthy(NaN) // => false
isNil :: a -> Boolean
isNil
returns true
given one of null
, undefined
, or NaN
. All other
values return false
.
import { isNil } from "eek-whales"
isNil(null) // => true
isNil(undefined) // => true
isNil(NaN) // => true
isNil("") // => false
isNil(0) // => false
isNil(42) // => false
isNil([]) // => false
isFunction :: a -> Boolean
isFunction
returns true
given a function or generator function. All other
values return false
.
import { isFunction } from "eek-whales"
const generator = function* () {
yield "a"
}
const fn = <T>(x: T): T => x
isFunction(fn) // => true
isFunction(<T>(x: T): T => x) // => true
isFunction(generator) // => true
isFunction(function* () {
yield "a"
}) // => true
isFunction([]) // => false
isDate :: a -> Boolean
isDate
returns true
given a date object. All other values return false
.
import { isDate } from "eek-whales"
isDate(new Date()) // => true
isDate(new Date(2023, 1, 1)) // => true
isDate(Date.now()) // => false
isDate() // => false
isDate("Wed Feb 01 2023 00:00:00 GMT-0500 (Eastern Standard Time)") // => false
isIterable :: a -> Boolean
isIterable
returns true
given a value with a Symbol.iterator
static
method.
import { isIterable } from "eek-whales"
isIterable("hello world") // => true
isIterable([1, 2, 3]) // => true
isIterable(new Uint8Array([10, 20, 30, 40, 50])) // => true
isIterable(
new Map([
["a", 1],
["b", 10],
["c", 100],
]),
) // => true
isIterable(new Set([0, 1, 1, 2, 3, 5, 8, 13, 21, 34])) // => true
isIterable(42) // => false
isIterable({}) // => false
isIterable() // => false
const customIterable = {
*[Symbol.iterator]() {
yield 1
yield 2
yield 3
},
}
isIterable(customIterable) // => true
isSetoid :: a -> Boolean
isSetoid
returns true
given an object/class with an equals
or
fantasy-land/equals
method. All other values return false
. This module
relies on duck typing to check if a value is a Setoid. It does NOT validate
any of the required algebraic laws (reflexivity, symmetry, and transitivity) as
laid out in the Fantasy Land Specification. Validating the laws is not
possible without knowing the type of value that will be passed to the equals
method in advance and that will vary depending on the Setoid implementation.
import { isSetoid } from "eek-whales"
import { Min, Max } from "eek-whales"
isSetoid(Min) // => true
isSetoid(Max) // => true
isSetoid("hello world") // => false
interface NumericSetoid {
value: number
equals: (n: NumericSetoid) => boolean
}
const mySetoid = (x: number) => ({
value: x,
equals: (y: NumericSetoid) => x === y.value,
})
isSetoid(mySetoid(42)) // => true
isSetoid(mySetoid) // => false
inspect :: a -> String
inspect
returns a string representation of the given value. Useful as a helper
function for creating toString
methods for ADTs.
import { inspect } from "eek-whales"
inspect("hello world") // => "hello world"
inspect(42) // => "42"
inspect([1, 2, 3]) // => "[1, 2, 3]"
inspect(undefined) // => "undefined"
inspect(<T>(x: T): T => x) // => "(x) => x"
inspect(new TypeError("FOO")) // => "TypeError: FOO"
nodeInspect :: Symbol
Using nodeInspect
in the ADTs allows for defining custom console.log
output
for Node.js without the need to import
the util
module. This makes it
unnecessary to verify a Node.js environment.
import { inspect, nodeInspect } from "eek-whales"
const Identity = x => ({
// ...
toString() {
return `Identity(${inspect(x)})`
},
[nodeInspect]() {
return this.toString()
},
})
random :: (Number | Undefined) -> Number
A pseudorandom number generator that accepts a seed number as input for
reproducible output. By default, the seed is the number returned by
Date.now()
. The returned floating point number will be between 0 and 1, not
including 1; [0, 1)
. The random number is generated using a linear
congruential generator algorithm with the following values:
multiplier (a) | increment (c) | modulus (m) |
---|---|---|
1103515245 | 12345 | 231 |
import { random } from "eek-whales"
random() // => 0.0469970703125
random() // => 0.871337890625
random() // => 0.1737060546875
random(1001001) // => 0.707733154296875
random(1001001) // => 0.707733154296875
random(0) // => 0
random(1) // => 0.51385498046875