eek-whales v0.3.0
EEK-Whales
A collection of JavaScript/TypeScript modules for functional programming
API
Combinators
Point-free Functions
- equals :: 
Setoid a => a -> a-> Booleanora -> b -> Boolean 
Classify Functions
Predicate Functions
- 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 
Showable
- inspect :: 
a -> String - nodeInspect :: 
Symbol 
Number
- random :: 
(Number | Undefined) -> Number 
Combinators
identity
identity :: a -> a
I :: a -> aThis 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) // => 42constant
constant :: a -> b -> aThis 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"Point-free Functions
equals
equals :: Setoid a => a -> a -> Boolean
equals :: a -> b -> BooleanThe 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))                // => falseClassify Functions
getType
getType :: a -> StringgetType 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
is :: String -> a -> BooleanThe 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)))  // => truePredicate Functions
isEqual
isEqual :: a -> b -> BooleanThe 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")   // => falseisSame
isSame :: a -> b -> BooleanThe 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)  // => falseisSameType
isSameType :: a -> b -> BooleanisSameType 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 ({}) ([])            // => falseisTruthy
isTruthy :: a -> BooleanisTruthy 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)         // => falseisNil
isNil :: a -> BooleanisNil 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([])         // => falseisFunction
isFunction :: a -> BooleanisFunction 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([])                         // => falseisDate
isDate :: a -> BooleanisDate 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)") // => falseisIterable
isIterable :: a -> BooleanisIterable 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)  // => trueisSetoid
isSetoid :: a -> BooleanisSetoid 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)      // => falseShowable
inspect
inspect :: a -> Stringinspect 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
nodeInspect :: SymbolUsing 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()
  }
})Number
random
random :: (Number | Undefined) -> NumberA 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