mirror of
https://github.com/rjNemo/functional-programming-jargon
synced 2026-06-11 04:56:40 +00:00
In-depth proofreading and correcting
This commit is contained in:
parent
b90ba66787
commit
6ddf6bb3e1
1 changed files with 77 additions and 50 deletions
119
readme.md
119
readme.md
|
|
@ -13,10 +13,11 @@
|
||||||
const sum = (a, b) => a + b;
|
const sum = (a, b) => a + b;
|
||||||
|
|
||||||
const arity = sum.length;
|
const arity = sum.length;
|
||||||
console.log(arity);
|
console.log(arity); // 2
|
||||||
// => 2
|
|
||||||
// The arity of sum is 2
|
// The arity of sum is 2
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Higher-Order Functions (HOF)
|
## Higher-Order Functions (HOF)
|
||||||
|
|
@ -25,13 +26,13 @@ console.log(arity);
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const filter = (pred, xs) => {
|
const filter = (pred, xs) => {
|
||||||
const result = [];
|
const result = [];
|
||||||
for (var idx = 0; idx < xs.length; idx += 1) {
|
for (var idx = 0; idx < xs.length; idx++) {
|
||||||
if (pred(xs[idx])) {
|
if (pred(xs[idx])) {
|
||||||
result.push(xs[idx]);
|
result.push(xs[idx]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return result;
|
||||||
return result;
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -40,7 +41,7 @@ const is = type => x => Object(x) instanceof type;
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
filter(is(Number), [0, '1', 2, null]); //=> [0, 2]
|
filter(is(Number), [0, '1', 2, null]); // [0, 2]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Partial Application
|
## Partial Application
|
||||||
|
|
@ -55,7 +56,7 @@ let sum = (a, b) => a + b;
|
||||||
let partial = sum.bind(null, 40);
|
let partial = sum.bind(null, 40);
|
||||||
|
|
||||||
// Invoking it with `b`
|
// Invoking it with `b`
|
||||||
partial(2); //=> 42
|
partial(2); // 42
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -71,6 +72,7 @@ let curriedSum = (a) => (b) => a + b;
|
||||||
|
|
||||||
curriedSum(40)(2) // 42.
|
curriedSum(40)(2) // 42.
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Composition
|
## Composition
|
||||||
|
|
@ -78,13 +80,12 @@ curriedSum(40)(2) // 42.
|
||||||
> A function which combines two values of a given type (usually also some kind of functions) into a third value of the same type.
|
> A function which combines two values of a given type (usually also some kind of functions) into a third value of the same type.
|
||||||
|
|
||||||
The most straightforward type of composition is called "normal function composition".
|
The most straightforward type of composition is called "normal function composition".
|
||||||
It allows you to combines functions that accept and return a single value.
|
It allows you to combine functions that accept and return a single value.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const compose = (f, g) => a => f(g(a)) // Definition
|
const compose = (f, g) => a => f(g(a)) // Definition
|
||||||
const floorAndToString = compose((val)=> val.toString(), Math.floor) //Usage
|
const floorAndToString = compose((val) => val.toString(), Math.floor) // Usage
|
||||||
floorAndToString(121.212121) // "121"
|
floorAndToString(121.212121) // "121"
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -97,9 +98,9 @@ input values, without any side effects.
|
||||||
```js
|
```js
|
||||||
let greet = "yo";
|
let greet = "yo";
|
||||||
|
|
||||||
greet.toUpperCase(); // YO;
|
greet.toUpperCase(); // "YO"
|
||||||
|
|
||||||
greet // yo;
|
greet // "yo"
|
||||||
```
|
```
|
||||||
|
|
||||||
As opposed to:
|
As opposed to:
|
||||||
|
|
@ -121,16 +122,21 @@ numbers // []
|
||||||
```js
|
```js
|
||||||
console.log("IO is a side effect!");
|
console.log("IO is a side effect!");
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Idempotency
|
## Idempotency
|
||||||
|
|
||||||
> A function is said to be idempotent if it has no side-effects on multiple
|
> A function is said to be idempotent if it has no side-effects on multiple
|
||||||
executions with the the same input parameters.
|
executions with the same input parameters.
|
||||||
|
|
||||||
`f(f(x)) = f(x)`
|
```js
|
||||||
|
f(f(x)) = f(x)
|
||||||
|
```
|
||||||
|
|
||||||
`Math.abs(Math.abs(10))`
|
```js
|
||||||
|
Math.abs(Math.abs(10))
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -168,7 +174,7 @@ Points-free function definitions look just like normal assignments without `func
|
||||||
|
|
||||||
## Categories
|
## Categories
|
||||||
|
|
||||||
> Objects with associated functions that adhere certain rules. E.g. [monoid](#monoid)
|
> Objects with associated functions that adhere to certain rules. E.g. [Monoid](#monoid)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -181,6 +187,7 @@ Points-free function definitions look just like normal assignments without `func
|
||||||
Object.freeze({name: 'John', age: 30}) // The `freeze` function enforces immutability.
|
Object.freeze({name: 'John', age: 30}) // The `freeze` function enforces immutability.
|
||||||
(a) => a
|
(a) => a
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that value-containing structures such as [Functor](#functor), [Monad](#monad) etc. are themselves values. This means, among other things, that they can be nested within each other.
|
Note that value-containing structures such as [Functor](#functor), [Monad](#monad) etc. are themselves values. This means, among other things, that they can be nested within each other.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -188,29 +195,32 @@ Note that value-containing structures such as [Functor](#functor), [Monad](#mona
|
||||||
## Constant
|
## Constant
|
||||||
|
|
||||||
> An immutable reference to a value. Not to be confused with `Variable` - a reference to a value which can at any point be updated to point to a different value.
|
> An immutable reference to a value. Not to be confused with `Variable` - a reference to a value which can at any point be updated to point to a different value.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const five = 5
|
const five = 5
|
||||||
const john = {name: 'John', age: 30}
|
const john = {name: 'John', age: 30}
|
||||||
```
|
```
|
||||||
|
|
||||||
Constants are referentially transparent. That is, they can be replaced with the values that they represent without affecting the result.
|
Constants are referentially transparent. That is, they can be replaced with the values that they represent without affecting the result.
|
||||||
|
|
||||||
In other words with the above two constants the expression:
|
In other words with the above two constants the expression:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
john.age + five === ({name: 'John', age: 30}).age + (5)
|
john.age + five === ({name: 'John', age: 30}).age + (5)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Should always return `true`.
|
Should always return `true`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Functor
|
## Functor
|
||||||
|
|
||||||
> An object with a `map` function that adhere to certains rules. `Map` runs a function on values in an object and returns a new object.
|
> An object with a `map` function that adheres to certains rules. `map` runs a function on values in an object and returns a new object.
|
||||||
|
|
||||||
Simplest functor in javascript is an `Array`
|
Simplest functor in javascript is an `Array`:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
[2,3,4].map( n => n * 2 ); // [4,6,8]
|
[2, 3, 4].map(n => n * 2); // [4, 6, 8]
|
||||||
```
|
```
|
||||||
|
|
||||||
Let `func` be an object implementing a `map` function, and `f`, `g` be arbitrary functions, then `func` is said to be a functor if the map function adheres to the following rules:
|
Let `func` be an object implementing a `map` function, and `f`, `g` be arbitrary functions, then `func` is said to be a functor if the map function adheres to the following rules:
|
||||||
|
|
@ -226,11 +236,13 @@ func.map(x => f(g(x))) == func.map(g).map(f)
|
||||||
```
|
```
|
||||||
|
|
||||||
We can now see that `Array` is a functor because it adheres to the functor rules!
|
We can now see that `Array` is a functor because it adheres to the functor rules!
|
||||||
|
|
||||||
```js
|
```js
|
||||||
[1, 2, 3].map(x => x); // = [1, 2, 3]
|
[1, 2, 3].map(x => x); // = [1, 2, 3]
|
||||||
```
|
```
|
||||||
|
|
||||||
and
|
and
|
||||||
|
|
||||||
```js
|
```js
|
||||||
let f = x => x + 1;
|
let f = x => x + 1;
|
||||||
let g = x => x * 2;
|
let g = x => x * 2;
|
||||||
|
|
@ -238,16 +250,18 @@ let g = x => x * 2;
|
||||||
[1, 2, 3].map(x => f(g(x))); // = [3, 5, 7]
|
[1, 2, 3].map(x => f(g(x))); // = [3, 5, 7]
|
||||||
[1, 2, 3].map(g).map(f); // = [3, 5, 7]
|
[1, 2, 3].map(g).map(f); // = [3, 5, 7]
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Pointed Functor
|
## Pointed Functor
|
||||||
> A functor with an `of` method. `Of` puts _any_ single value into a functor.
|
> A functor with an `of` method. `of` puts _any_ single value into a functor.
|
||||||
|
|
||||||
|
Array implementation:
|
||||||
|
|
||||||
Array Implementation:
|
|
||||||
```js
|
```js
|
||||||
Array.prototype.of = (v) => [v];
|
Array.prototype.of = (v) => [v];
|
||||||
|
|
||||||
[].of(1) // [1]
|
[].of(1) // [1]
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -259,11 +273,13 @@ Array Implementation:
|
||||||
Map is the same as a lift over a one-argument function:
|
Map is the same as a lift over a one-argument function:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
lift(n => n * 2)([2,3,4]); // [4,6,8]
|
lift(n => n * 2)([2, 3, 4]); // [4, 6, 8]
|
||||||
```
|
```
|
||||||
|
|
||||||
Unlike map lift can be used to combine values from multiple arrays:
|
Unlike map lift can be used to combine values from multiple arrays:
|
||||||
```
|
|
||||||
lift((a, b) => a * b)([1, 2], [3]); // [3, 6]
|
```js
|
||||||
|
lift((a, b) => a * b)([1, 2], [3]); // [3, 6]
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -296,15 +312,17 @@ referentially transparent.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
let rand = function*() {
|
let rand = function*() {
|
||||||
while(1<2) {
|
while (1 < 2) {
|
||||||
yield Math.random();
|
yield Math.random();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
let randIter = rand();
|
let randIter = rand();
|
||||||
randIter.next(); // Each exectuion gives a random value, expression is evaluated on need.
|
randIter.next(); // Each execution gives a random value, expression is evaluated on need.
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Monoid
|
## Monoid
|
||||||
|
|
@ -342,23 +360,23 @@ The identity value is empty array `[]`
|
||||||
```js
|
```js
|
||||||
[1, 2].concat([]); // [1, 2]
|
[1, 2].concat([]); // [1, 2]
|
||||||
```
|
```
|
||||||
Functions also form a monoid with the normal functional compositon as an operation and the function which returns its input `(a) => a`
|
|
||||||
|
|
||||||
|
Functions also form a monoid with the normal functional composition as an operation and the function which returns its input `(a) => a`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Monad
|
## Monad
|
||||||
|
|
||||||
> A monad is an object with [`of`](#pointed-functor) and `chain` functions. `Chain` is like [map](#functor) except it unnests the resulting nested object.
|
> A monad is an object with [`of`](#pointed-functor) and `chain` functions. `chain` is like [`map`](#functor) except it un-nests the resulting nested object.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
['cat,dog','fish,bird'].chain(a => a.split(',')) // ['cat','dog','fish','bird']
|
['cat,dog', 'fish,bird'].chain(a => a.split(',')) // ['cat', 'dog', 'fish', 'bird']
|
||||||
|
|
||||||
//Contrast to map
|
//Contrast to map
|
||||||
['cat,dog','fish,bird'].map(a => a.split(',')) // [['cat','dog'], ['fish','bird']]
|
['cat,dog', 'fish,bird'].map(a => a.split(',')) // [['cat', 'dog'], ['fish', 'bird']]
|
||||||
```
|
```
|
||||||
|
|
||||||
You may also see `of` and `chain` referred to as `return` and `bind` (not be confused with the JS keyword/function...) in languages which provide Monad-like constructs as part of their standard library (e.g. Haskell, F#), on [Wikipedia](https://en.wikipedia.org/wiki/Monad_%28functional_programming%29) and in other literature. It's also important to note that `return` and `bind` are not part of the [Fantasy Land spec](https://github.com/fantasyland/fantasy-land) and are mentioned here only for the sake of people interested in learning more about Monads.
|
You may also see `of` and `chain` referred to as `return` and `bind` (not to be confused with the JS keyword/function...) in languages which provide monad-like constructs as part of their standard library (e.g. Haskell, F#), on [Wikipedia](https://en.wikipedia.org/wiki/Monad_%28functional_programming%29) and in other literature. It's also important to note that `return` and `bind` are not part of the [Fantasy Land spec](https://github.com/fantasyland/fantasy-land) and are mentioned here only for the sake of people interested in learning more about monads.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -375,22 +393,25 @@ let CoIdentity = v => ({
|
||||||
```
|
```
|
||||||
|
|
||||||
Extract takes a value out of a functor.
|
Extract takes a value out of a functor.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
CoIdentity(1).extract() // 1
|
CoIdentity(1).extract() // 1
|
||||||
```
|
```
|
||||||
|
|
||||||
Extend runs a function on the comonad. The function should return the same type as the Comonad.
|
Extend runs a function on the comonad. The function should return the same type as the comonad.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
CoIdentity(1).extend(co => co.extract() + 1) // CoIdentity(2)
|
CoIdentity(1).extend(co => co.extract() + 1) // CoIdentity(2)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Applicative Functor
|
## 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.
|
> 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.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
[(a)=> a + 1].ap([1]) // [2]
|
[(a) => a + 1].ap([1]) // [2]
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -406,6 +427,7 @@ CoIdentity(1).extend(co => co.extract() + 1) // CoIdentity(2)
|
||||||
> A pair of transformations between 2 types of objects that is structural in nature and no data is lost.
|
> A pair of transformations between 2 types of objects that is structural in nature and no data is lost.
|
||||||
|
|
||||||
For example, 2D coordinates could be stored as an array `[2,3]` or object `{x: 2, y: 3}`.
|
For example, 2D coordinates could be stored as an array `[2,3]` or object `{x: 2, y: 3}`.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Providing functions to convert in both directions makes them isomorphic.
|
// Providing functions to convert in both directions makes them isomorphic.
|
||||||
const pairToCoords = (pair) => ({x: pair[0], y: pair[1]})
|
const pairToCoords = (pair) => ({x: pair[0], y: pair[1]})
|
||||||
|
|
@ -423,7 +445,8 @@ pairToCoords(coordsToPair({x: 1, y: 2})) // {x: 1, y: 2}
|
||||||
|
|
||||||
> An object that has an `equals` function which can be used to compare other objects of the same type.
|
> An object that has an `equals` function which can be used to compare other objects of the same type.
|
||||||
|
|
||||||
Make array a setoid.
|
Make array a setoid:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
Array.prototype.equals = arr => {
|
Array.prototype.equals = arr => {
|
||||||
var len = this.length
|
var len = this.length
|
||||||
|
|
@ -446,7 +469,7 @@ Array.prototype.equals = arr => {
|
||||||
|
|
||||||
## Semigroup
|
## Semigroup
|
||||||
|
|
||||||
An object that has a `concat` function that combines it with another object of the same type.
|
> An object that has a `concat` function that combines it with another object of the same type.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
[1].concat([2]) // [1, 2]
|
[1].concat([2]) // [1, 2]
|
||||||
|
|
@ -456,7 +479,7 @@ An object that has a `concat` function that combines it with another object of t
|
||||||
|
|
||||||
## Foldable
|
## Foldable
|
||||||
|
|
||||||
> An object that has a reduce function that can transform that object into some other type.
|
> An object that has a `reduce` function that can transform that object into some other type.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
let sum = list => list.reduce((acc, val) => acc + val, 0);
|
let sum = list => list.reduce((acc, val) => acc + val, 0);
|
||||||
|
|
@ -468,11 +491,13 @@ sum([1, 2, 3]) // 6
|
||||||
## Traversable
|
## Traversable
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Type Signatures
|
## Type Signatures
|
||||||
|
|
||||||
> Often functions will include comments that indicate the types of their arguments and return types.
|
> Often functions will include comments that indicate the types of their arguments and return types.
|
||||||
|
|
||||||
There's quite a bit variance across the community but they often follow the following patterns:
|
There's quite a bit of variance across the community but they often follow the following patterns:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// functionName :: firstArgType -> secondArgType -> returnType
|
// functionName :: firstArgType -> secondArgType -> returnType
|
||||||
|
|
||||||
|
|
@ -489,8 +514,10 @@ If a function accepts another function as an argument it is wrapped in parenthes
|
||||||
// call :: (a -> b) -> a -> b
|
// call :: (a -> b) -> a -> b
|
||||||
let call = f => x => f(x)
|
let call = f => x => f(x)
|
||||||
```
|
```
|
||||||
The letters `a`, `b`, `c`, `d` are used to signify that the argument can be of any type. For this map it takes a function that transforms a value of some type `a` into another type `b`, an array of values of type `a`, and returns an array of values of type `b`.
|
|
||||||
|
The letters `a`, `b`, `c`, `d` are used to signify that the argument can be of any type. For this `map` it takes a function that transforms a value of some type `a` into another type `b`, an array of values of type `a`, and returns an array of values of type `b`.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// map :: (a -> b) -> [a] -> [b]
|
// map :: (a -> b) -> [a] -> [b]
|
||||||
let map = f => list => list.map(f)
|
let map = f => list => list.map(f)
|
||||||
```
|
```
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue