The original author of this article has not been completed, interested can go to the original or translation address to follow the update

The main purpose of this article is to provide an easy to understand way to explain common theoretical terminology concepts in functional programming

Arity: specifies the number of parameters

Arity refers to the number of arguments ina function. This keyword is derived from unary, binary, ternary, etc., and consists of -ary and -ity. For example, if a function allows two arguments, it is called a so-called binary function, or a function with two arguments. These functions are sometimes called “dyadic “by people who like Latin grammar. In the same way, equations with uncertain parameters are called variadic.

const sum = (a, b) => a + b;

const arity = sum.length;
console.log(arity);
// => 2
// The arity of sum is 2Copy the code

Higher-order Functions (HOF): higher-order Functions

A function that takes a function as an argument becomes an advanced function and can optionally return a function or another type

const filter = (pred, xs) => {
  const result = [];
  for (var idx = 0; idx < xs.length; idx += 1) {
    if (pred(xs[idx])) {
      result.push(xs[idx]);
    }
  }
  return result;
};Copy the code
const is = type => x => Object(x) instanceof type;Copy the code
filter(is(Number), [0, '1', 2, null]); / / = > [0, 2)Copy the code

Partial Application: indicates Partial encapsulation

The process of encapsulating a multi-parameter function into a function with a fixed number of parameters is called Partial Application

let sum = (a, b) => a + b; // partially applying `a` to `40` let partial = sum.bind(null, 40); // Invoking it with `b` partial(2); / / = > 42Copy the code

Currying

A function with N parameter values can be converted into a combination of N unary functions. The difference between a Partial Application and a Currying function is that a Partial Application can eventually generate a function that accepts multiple values. Each function in a sequence of functions that is curried can only take one argument

let sum = (a, b) => a + b;

let curriedSum = (a) => (b) => a + b;

curriedSum(40)(2) // 42.Copy the code

Combination of Composition:

It feels a bit like a Decorator in design mode, a function that converts a combination of two specified types to a new value

The most common combination is the common function combination, which allows you to combine different functions into a single function that returns a single value

const compose = (f, g) => a => f(g(a)) // Definition const floorAndToString = compose((val)=> val.toString(), Math.floor) //Usage floorAndToString(121.212121)Copy the code

Purity: pure functions

A function that has no side effects and whose return value is determined only by the input becomes a pure function

let greet = "yo";

greet.toUpperCase(); // YO;

greet // yo;Copy the code

As opposed to:

let numbers = [1, 2, 3];

numbers.splice(0); // [1, 2, 3]

numbers // []Copy the code

-sheldon: Well, there are Side effects

If a function, in addition to returning a value, modifies some other state, or has observable interactions with external functions, etc

console.log("IO is a side effect!" );Copy the code

Idempotency: idempotence

A function that is executed multiple times without side effects is said to be idempotent

f(f(x)) = f(x)

Math.abs(Math.abs(10))

Point-Free Style

A function Style that does not have linearly defined parameters is called point-free Style, and this type usually requires currying or higher-order functions.

// Given
let map = fn => list => list.map(fn);
let add = (a, b) => a + b;

// Then

// Not points-free - `numbers` is an explicit parameter
let incrementAll = (numbers) => map(add(1))(numbers);

// Points-free - The list is an implicit parameter
let incrementAll2 = map(add(1));Copy the code

IncrementAll explicitly specifies the numbers parameter, and incrementAll2 encapsulates the parameters without explicitly specifying the numbers parameter, so it can be referred to as Points Free. In general, points-free functions are not defined with the usual function or => keyword.

Contracts

no

Guarded Functions

no

Classification of Categories:

Objects associated with functions that follow certain rules, such as monoid

Value: the Value

Complex or primitive values are commonly used in calculations, including functions. In general, values in functional programming are considered immutable.

5
Object.freeze({name: 'John', age: 30}) // The `freeze` function enforces immutability.
(a) => aCopy the code

Note that structures such as Functor and Monad that contain other values are themselves values, that is, these compound values can also contain each other.

Constant: Constant

An immutable reference to a value should not be confused with a variable. Variables are references that can be changed at any point.

const five = 5
const john = {name: 'John', age: 30}Copy the code

Constants are generally considered transparent, that is, they can be replaced by the values themselves without affecting the final result of the calculation. The two constants above can also be expressed as follows:

john.age + five === ({name: 'John', age: 30}).age + (5)
Copy the code

The above expression always returns true.

Functor

Functor is an object that can refer to a map function. The simplest function in JavaScript is Array.

[2,3,4]. Map (n => n * 2); / /,6,8 [4]Copy the code

Given that func is constructed as an object that implements a map function, and f and g are arbitrary functions, func can be called a functor as long as func follows 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:

func.map(x => x) == funcCopy the code
func.map(x => f(g(x))) == func.map(g).map(f)Copy the code

Array is called Functor because it follows the following rules:

[1, 2, 3].map(x => x); // = [1, 2, 3]Copy the code
let f = x => x + 1;
let 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]Copy the code

Pointed Functor

Functor implements the of method, and of converts any single value to a Functor

The conservative Functor implementation in Array is:

  Array.prototype.of = (v) => [v];
  
  [].of(1) // [1]Copy the code

Lift

Lift is similar to Map, but it can be used with more than one Functors:

In single-valued functions, Map and Lift work in the same way:

Lift (n => n * 2)([2,3,4]); / /,6,8 [4]Copy the code

Lift allows you to enter multiple values:

lift((a, b) => a * b)([1, 2], [3]); / / [3, 6]Copy the code

Referential Transparency

An expression that can be replaced directly with its value without affecting program performance is called a transparent reference

For example, we have a reference called greet

let greet = () => "Hello World!" ;Copy the code

Any forgreet()Can be calledHello World!I can replace it directly, so I can replace itgreetThis is called a transparent reference.

Equational Reasoning

When an application is composed of expressions without any side effects, the system can be derived from parts

Lazy evaluation: Lazy evaluation

Lazy evaluation is a mechanism for calculating only when a value is needed. In functional languages, this mechanism allows operations on nearly infinite lists.

let rand = function*() { while(1<2) {="" yield="" math.random(); ="" }="" }<="" code="">Copy the code
let randIter = rand();
randIter.next(); // Each exectuion gives a random value, expression is evaluated on need.Copy the code

Monoid: Monoid

A monOID is a data type that, when combined with an identity value, does not affect the existing result

The simplest Monoid would look like this:

1 + 1; / / 2Copy the code

The data type is number and the function is + :

1 + 0; / / 1Copy the code

The value of the identity is 0, and adding 0 to any number does not change the value. Sometimes, monoid types do different swaps without affecting the result:

1 + (2 + 3) == (1 + 2) + 3; // trueCopy the code

An array join can also be thought of as a monoid:

[1, 2].concat([3, 4]); // [1, 2, 3, 4]Copy the code

Identity is an empty array: []

[1, 2].concat([]); / / [1, 2]Copy the code

Monad

A Monad is an object that has of and chain functions. Chain is like map except that it flattens out the nested result that you end up with.

['cat,dog','fish,bird'].chain(a => a.split(',')) // ['cat','dog','fish','bird']

//Contrast to map
['cat,dog','fish,bird'].map(a => a.split(',')) // [['cat','dog'], ['fish','bird']]Copy the code

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 and in other literature. It’s also important to note that return and bind are not part of the Fantasy Land spec and are mentioned here only for the sake of people interested in learning more about Monads.

More than Comonad: list

An object that implements the extract and extend functions

let CoIdentity = v => ({
    val: v,
    extract: this.v,
    extend: f => CoIdentity(f(this))
})Copy the code

Extract can spit values out of Functor:

CoIdentity(1).extract() // 1Copy the code

Extend returns a function that returns the same value as Commonad:

CoIdentity(1).extend(co => co.extract() + 1) // CoIdentity(2)Copy the code

“Applicative” is Functor

An Applicative Functor is an object that implements an AP function that converts a value in one object to a value of the same type in another object

[(a)=> a + 1].ap([1]) // [2]Copy the code

Morphism: Morphism

A transformation function

Isomorphism: homomorphism conversion

A transformation that represents the same data stored in different ways

For example, a two-dimensional array can be stored as array: [2,3] or object: {x: 2, y: 3}.

// Providing functions to convert in both directions makes them isomorphic.
const pairToCoords = (pair) => ({x: pair[0], y: pair[1]})

const coordsToPair = (coords) => [coords.x, coords.y]

coordsToPair(pairToCoords([1, 2])) // [1, 2]

pairToCoords(coordsToPair({x: 1, y: 2})) // {x: 1, y: 2}Copy the code

Setoid

An object that implements equals, which can be compared to other objects to determine whether they are of the same type, is called a Setoid.

The following extension to the prototype can change Array to Setoid.

Array.prototype.equals = arr => { var len = this.length if (len ! = arr.length) { return false } for (var i = 0; i < len; i++) { if (this[i] ! == arr[i]) { return false } } return true } [1, 2].equals([1, 2]) // true [1, 2].equals([0]) // falseCopy the code

Semigroup: Semigroup

One has a concat, which converts another object into a function of the same type. The object of the function is called Semigroup.

[1].concat([2]) // [1, 2]Copy the code

Foldable: folding

Objects that implement the Reduce function, which translates an object into another type of function, are called Foldable objects.

let sum = list => list.reduce((acc, val) => acc + val, 0);
sum([1, 2, 3]) // 6Copy the code

Traversable

no

Type Signatures: Type Signatures

In general, functions are commented to indicate their parameter types and return value types

// functionName :: firstArgType -> secondArgType -> returnType

// add :: Number -> Number -> Number
let add = x => y => x + y

// increment :: Number -> Number
let increment = x => x + 1Copy the code

If a function takes other functions as arguments, for example:

// call :: (a -> b) -> a -> b
let call = f => x => f(x)Copy the code

The a, b, c, and D here indicate that the parameter can be of any type, but it will convert type A to another type B, whereas for the map below, its comments indicate that it will enter a list of type A and then convert it to another list containing type B.

// map :: (a -> b) -> [a] -> [b]
let map = f => list =>  list.map(f)Copy the code