Merge remote-tracking branch 'hemanth/master'

This commit is contained in:
jethro larson 2016-06-06 15:49:11 -07:00
commit de31b94a72
2 changed files with 135 additions and 47 deletions

23
package.json Normal file
View file

@ -0,0 +1,23 @@
{
"name": "functional-programming-jargons",
"version": "1.0.0",
"description": "Jargon from the functional programming world in simple terms!",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"toc": "roadmarks"
},
"repository": {
"type": "git",
"url": "git+https://github.com/hemanth/functional-programming-jargon.git"
},
"author": "hemanth",
"license": "MIT",
"bugs": {
"url": "https://github.com/hemanth/functional-programming-jargon/issues"
},
"homepage": "https://github.com/hemanth/functional-programming-jargon#readme",
"devDependencies": {
"roadmarks": "^1.6.3"
}
}

159
readme.md
View file

@ -6,6 +6,43 @@ The goal of this document is to define jargon from functional programming in pla
> Where applicable, this document uses terms defined in the [Fantasy Land spec](https://github.com/fantasyland/fantasy-land) > Where applicable, this document uses terms defined in the [Fantasy Land spec](https://github.com/fantasyland/fantasy-land)
<!-- RM(noparent,notop) -->
* [Arity](#arity)
* [Higher-Order Functions (HOF)](#higher-order-functions-hof)
* [Partial Application](#partial-application)
* [Currying](#currying)
* [Composition](#composition)
* [Purity](#purity)
* [Side effects](#side-effects)
* [Idempotency](#idempotency)
* [Point-Free Style](#point-free-style)
* [Contracts](#contracts)
* [Guarded Functions](#guarded-functions)
* [Categories](#categories)
* [Value](#value)
* [Constant](#constant)
* [Functor](#functor)
* [Pointed Functor](#pointed-functor)
* [Lift](#lift)
* [Referential Transparency](#referential-transparency)
* [Equational Reasoning](#equational-reasoning)
* [Lazy evaluation](#lazy-evaluation)
* [Monoid](#monoid)
* [Monad](#monad)
* [Comonad](#comonad)
* [Applicative Functor](#applicative-functor)
* [Morphism](#morphism)
* [Isomorphism](#isomorphism)
* [Setoid](#setoid)
* [Semigroup](#semigroup)
* [Foldable](#foldable)
* [Traversable](#traversable)
* [Type Signatures](#type-signatures)
<!-- /RM -->
## Arity ## Arity
> The number of arguments a function takes. From words like unary, binary, ternary, etc. This word has the distinction of being composed of two suffixes, "-ary" and "-ity." Addition, for example, takes two arguments, and so it is defined as a binary function or a function with an arity of two. Such a function may sometimes be called "dyadic" by people who prefer Greek roots to Latin. Likewise, a function that takes a variable number of arguments is called "variadic," whereas a binary function must be given two and only two arguments, currying and partial application notwithstanding (see below). > The number of arguments a function takes. From words like unary, binary, ternary, etc. This word has the distinction of being composed of two suffixes, "-ary" and "-ity." Addition, for example, takes two arguments, and so it is defined as a binary function or a function with an arity of two. Such a function may sometimes be called "dyadic" by people who prefer Greek roots to Latin. Likewise, a function that takes a variable number of arguments is called "variadic," whereas a binary function must be given two and only two arguments, currying and partial application notwithstanding (see below).
@ -14,10 +51,11 @@ The goal of this document is to define jargon from functional programming in pla
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)
@ -26,13 +64,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;
}; };
``` ```
@ -41,7 +79,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
@ -56,7 +94,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
``` ```
--- ---
@ -72,20 +110,17 @@ let curriedSum = (a) => (b) => a + b;
curriedSum(40)(2) // 42. curriedSum(40)(2) // 42.
``` ```
--- ---
## Composition ## Function Composition
> 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 act of putting two two functions together to form a third function so that the output of one function is the input of the other.
The most well-known type of composition is normal function composition.
It allows you to combines 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"
``` ```
--- ---
@ -98,9 +133,9 @@ input values, and does not produce 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:
@ -122,17 +157,24 @@ numbers // []
```js ```js
console.log("IO is a side effect!"); console.log("IO is a side effect!");
``` ```
--- ---
## Idempotent ## Idempotent
> A function is idempotent if reapplying it to its result does not produce a different result. > A function is idempotent if reapplying it to its result does not produce a different result.
`f(f(x)) = f(x)` ```js
f(f(x)) = f(x)
```
`Math.abs(Math.abs(10))` ```js
Math.abs(Math.abs(10))
```
`sort(sort(sort([2,1])))` ```js
sort(sort(sort([2,1])))
```
--- ---
@ -143,7 +185,7 @@ console.log("IO is a side effect!");
```js ```js
// Given // Given
let map = fn => list => list.map(fn); let map = fn => list => list.map(fn);
let add = (a, b) => a + b; let add = a => b => a + b;
// Then // Then
@ -170,7 +212,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)
--- ---
@ -185,6 +227,7 @@ Object.freeze({name: 'John', age: 30}) // The `freeze` function enforces immutab
[1] [1]
undefined undefined
``` ```
--- ---
## Constant ## Constant
@ -195,13 +238,15 @@ undefined
const five = 5 const five = 5
const john = {name: 'John', age: 30} const john = {name: 'John', age: 30}
``` ```
Constants are [referentially transparent](#referential-transparency). That is, they can be replaced with the values that they represent without affecting the result. Constants are [referentially transparent](#referential-transparency). 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`.
--- ---
@ -213,7 +258,7 @@ Should always return `true`.
A common functor in javascript is `Array` A common functor in javascript is `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:
@ -231,11 +276,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;
@ -243,16 +290,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` function that puts _any_ single value into that functor. > A functor with an `of` function that puts _any_ single value into that functor.
Array Implementation: Array Implementation:
```js
Array.prototype.of = (v) => [v];
[].of(1) // [1] ```js
Array.prototype.of = (v) => [v];
[].of(1) // [1]
``` ```
--- ---
@ -264,11 +313,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]
``` ```
--- ---
@ -301,15 +352,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 evluated on need. randIter.next(); // Each execution gives a random value, expression is evaluated on need.
``` ```
--- ---
## Monoid ## Monoid
@ -347,6 +400,7 @@ The identity value is empty array `[]`
```js ```js
[1, 2].concat([]); // [1, 2] [1, 2].concat([]); // [1, 2]
``` ```
If identity and compose functions are provided, functions themselves form a monoid: If identity and compose functions are provided, functions themselves form a monoid:
```js ```js
@ -356,18 +410,17 @@ var compose = (f, g) => x => f(g(x));
compose(foo, identity) ≍ compose(identity, foo) ≍ foo compose(foo, identity) ≍ compose(identity, foo) ≍ foo
``` ```
--- ---
## 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']]
``` ```
`of` is also known as `return` in other functional languages. `of` is also known as `return` in other functional languages.
@ -388,22 +441,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]
``` ```
--- ---
@ -419,6 +475,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]})
@ -436,7 +493,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
@ -459,7 +517,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]
@ -469,7 +527,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);
@ -481,11 +539,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
@ -502,8 +562,13 @@ 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)
``` ```
---
__P.S:__ Without the wonderful [contributions](https://github.com/hemanth/functional-programming-jargon/graphs/contributors) this repo would be meaningless!