An object that implements a map function which, while running over each value in the object to produce a new object, adheres to two rules:
Preserves identity
object.map(x => x) ≍ object
Composable
object.map(compose(f, g)) ≍ object.map(g).map(f)
(f, g are arbitrary functions)
A common functor in JavaScript is Array since it abides to the two functor rules:
;[1, 2, 3].map(x => x) // = [1, 2, 3]
and
const f = x => x + 1
const g = x => x * 2
;[1, 2, 3].map(x => f(g(x))) // = [3, 5, 7]
;[1, 2, 3].map(g).map(f) // = [3, 5, 7]
Pointed Functor
An object with an of function that puts any single value into it.
ES2015 adds Array.of making arrays a pointed functor.
Array.of(1) // [1]
Lifting
Lifting is when you take a value and put it into an object like a functor. If you lift a function into an Applicative Functor then you can make it work on values that are also in that functor.
Some implementations have a function called lift, or liftA2 to make it easier to run functions on functors.
const liftA2 = (f) => (a, b) => a.map(f).ap(b) // note it's `ap` and not `map`.
const mult = a => b => a * b
const liftedMult = liftA2(mult) // this function now works on functors like array
liftedMult([1, 2], [3]) // [3, 6]
liftA2(a => b => a + b)([1, 2], [3, 4]) // [4, 5, 5, 6]
Lifting a one-argument function and applying it does the same thing as map.
An applicative functor is an object with an ap function. ap applies a function in the object to a value in another object of the same type.
// Implementation
Array.prototype.ap = function (xs) {
return this.reduce((acc, f) => acc.concat(xs.map(f)), [])
}
// Example usage
;[(a) => a + 1].ap([1]) // [2]
This is useful if you have two objects and you want to apply a binary function to their contents.
// Arrays that you want to combine
const arg1 = [1, 3]
const arg2 = [4, 5]
// combining function - must be curried for this to work
const add = (x) => (y) => x + y
const partiallyAppliedAdds = [add].ap(arg1) // [(y) => 1 + y, (y) => 3 + y]
This gives you an array of functions that you can call ap on to get the result:
partiallyAppliedAdds.ap(arg2) // [5, 6, 7, 8]
Setoid
An object that has an equals function which can be used to compare other objects of the same type.
Make array a setoid:
Array.prototype.equals = function (arr) {
const len = this.length
if (len !== arr.length) {
return false
}
for (let i = 0; i < len; i++) {
if (this[i] !== arr[i]) {
return false
}
}
return true
}
;[1, 2].equals([1, 2]) // true
;[1, 2].equals([0]) // false
Semigroup
An object that has a concat function that combines it with another object of the same type.
;[1].concat([2]) // [1, 2]
Foldable
An object that has a reduce function that applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.
A lens is a structure (often an object or function) that pairs a getter and a non-mutating setter for some other data
structure.
// Using [Ramda's lens](http://ramdajs.com/docs/#lens)
const nameLens = R.lens(
// getter for name property on an object
(obj) => obj.name,
// setter for name property
(val, obj) => Object.assign({}, obj, {name: val})
)
Having the pair of get and set for a given data structure enables a few key features.
const person = {name: 'Gertrude Blanch'}
// invoke the getter
R.view(nameLens, person) // 'Gertrude Blanch'
// invoke the setter
R.set(nameLens, 'Shafi Goldwasser', person) // {name: 'Shafi Goldwasser'}
// run a function on the value in the structure
R.over(nameLens, uppercase, person) // {name: 'GERTRUDE BLANCH'}
Lenses are also composable. This allows easy immutable updates to deeply nested data.
// This lens focuses on the first item in a non-empty array
const firstLens = R.lens(
// get first item in array
xs => xs[0],
// non-mutating setter for first item in array
(val, [__, ...xs]) => [val, ...xs]
)
const people = [{name: 'Gertrude Blanch'}, {name: 'Shafi Goldwasser'}]
// Despite what you may assume, lenses compose left-to-right.
R.over(compose(firstLens, nameLens), uppercase, people) // [{'name': 'GERTRUDE BLANCH'}, {'name': 'Shafi Goldwasser'}]
Other implementations:
partial.lenses - Tasty syntax sugar and a lot of powerful features
Functor
An object that implements a
map
function which, while running over each value in the object to produce a new object, adheres to two rules:Preserves identity
Composable
(
f
,g
are arbitrary functions)A common functor in JavaScript is
Array
since it abides to the two functor rules:and
Pointed Functor
An object with an
of
function that puts any single value into it.ES2015 adds
Array.of
making arrays a pointed functor.Lifting
Lifting is when you take a value and put it into an object like a functor. If you lift a function into an Applicative Functor then you can make it work on values that are also in that functor.
Some implementations have a function called
lift
, orliftA2
to make it easier to run functions on functors.Lifting a one-argument function and applying it does the same thing as
map
.Monoid
An object with a function that "combines" that object with another of the same type.
One simple monoid is the addition of numbers:
In this case number is the object and
+
is the function.An "identity" value must also exist that when combined with a value doesn't change it.
The identity value for addition is
0
.It's also required that the grouping of operations will not affect the result (associativity):
Array concatenation also forms a monoid:
The identity value is empty array
[]
If identity and compose functions are provided, functions themselves form a monoid:
foo
is any function that takes one argument.Monad
A monad is an object with
of
andchain
functions.chain
is likemap
except it un-nests the resulting nested object.of
is also known asreturn
in other functional languages.chain
is also known asflatmap
andbind
in other languages.Comonad
An object that has
extract
andextend
functions.Extract takes a value out of a functor.
Extend runs a function on the comonad. The function should return the same type as the comonad.
Applicative Functor
An applicative functor is an object with an
ap
function.ap
applies a function in the object to a value in another object of the same type.This is useful if you have two objects and you want to apply a binary function to their contents.
This gives you an array of functions that you can call
ap
on to get the result:Setoid
An object that has an
equals
function which can be used to compare other objects of the same type.Make array a setoid:
Semigroup
An object that has a
concat
function that combines it with another object of the same type.Foldable
An object that has a
reduce
function that applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.Lens
A lens is a structure (often an object or function) that pairs a getter and a non-mutating setter for some other data structure.
Having the pair of get and set for a given data structure enables a few key features.
Lenses are also composable. This allows easy immutable updates to deeply nested data.
Other implementations: