mirror of
https://github.com/rjNemo/functional-programming-jargon
synced 2026-06-11 21:16:43 +00:00
Rename union type to sum type to complement with product type and change description and example to better match the concept
This commit is contained in:
parent
dedffb1663
commit
a30176c55c
1 changed files with 53 additions and 49 deletions
92
readme.md
92
readme.md
|
|
@ -56,8 +56,9 @@ __Table of Contents__
|
||||||
* [Foldable](#foldable)
|
* [Foldable](#foldable)
|
||||||
* [Traversable](#traversable)
|
* [Traversable](#traversable)
|
||||||
* [Type Signatures](#type-signatures)
|
* [Type Signatures](#type-signatures)
|
||||||
* [Union type](#union-type)
|
* [Algebraic data type](#algebraic-data-type)
|
||||||
* [Product type](#product-type)
|
* [Sum type](#sum-type)
|
||||||
|
* [Product type](#product-type)
|
||||||
* [Option](#option)
|
* [Option](#option)
|
||||||
* [Functional Programming Libraries in JavaScript](#functional-programming-libraries-in-javascript)
|
* [Functional Programming Libraries in JavaScript](#functional-programming-libraries-in-javascript)
|
||||||
|
|
||||||
|
|
@ -102,9 +103,9 @@ Partially applying a function means creating a new function by pre-filling some
|
||||||
// Helper to create partially applied functions
|
// Helper to create partially applied functions
|
||||||
// Takes a function and some arguments
|
// Takes a function and some arguments
|
||||||
const partial = (f, ...args) =>
|
const partial = (f, ...args) =>
|
||||||
// returns a function that takes the rest of the arguments
|
// returns a function that takes the rest of the arguments
|
||||||
(...moreArgs) =>
|
(...moreArgs) =>
|
||||||
// and calls the original function with all of them
|
// and calls the original function with all of them
|
||||||
f(...args, ...moreArgs)
|
f(...args, ...moreArgs)
|
||||||
|
|
||||||
// Something to apply
|
// Something to apply
|
||||||
|
|
@ -294,7 +295,7 @@ Math.abs(Math.abs(10))
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
sort(sort(sort([2, 1])))
|
sort(sort(sort([2,1])))
|
||||||
```
|
```
|
||||||
|
|
||||||
## Point-Free Style
|
## Point-Free Style
|
||||||
|
|
@ -368,7 +369,8 @@ To be a valid category 3 rules must be met:
|
||||||
|
|
||||||
Since these rules govern composition at very abstract level, category theory is great at uncovering new ways of composing things.
|
Since these rules govern composition at very abstract level, category theory is great at uncovering new ways of composing things.
|
||||||
|
|
||||||
### Further reading
|
__Further reading__
|
||||||
|
|
||||||
* [Category Theory for Programmers](https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/)
|
* [Category Theory for Programmers](https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/)
|
||||||
|
|
||||||
## Value
|
## Value
|
||||||
|
|
@ -519,9 +521,9 @@ Lazy evaluation is a call-by-need evaluation mechanism that delays the evaluatio
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const rand = function*() {
|
const rand = function*() {
|
||||||
while (1 < 2) {
|
while (1 < 2) {
|
||||||
yield Math.random()
|
yield Math.random()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -583,7 +585,7 @@ A monad is an object with [`of`](#pointed-functor) and `chain` functions. `chain
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Implementation
|
// Implementation
|
||||||
Array.prototype.chain = function (f) {
|
Array.prototype.chain = function(f){
|
||||||
return this.reduce((acc, it) => acc.concat(f(it)), [])
|
return this.reduce((acc, it) => acc.concat(f(it)), [])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -603,7 +605,7 @@ An object that has `extract` and `extend` functions.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const CoIdentity = (v) => ({
|
const CoIdentity = (v) => ({
|
||||||
val: v,
|
val: v,
|
||||||
extract () {
|
extract () {
|
||||||
return this.val
|
return this.val
|
||||||
},
|
},
|
||||||
|
|
@ -631,7 +633,7 @@ An applicative functor is an object with an `ap` function. `ap` applies a functi
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Implementation
|
// Implementation
|
||||||
Array.prototype.ap = function (xs) {
|
Array.prototype.ap = function(xs){
|
||||||
return this.reduce((acc, f) => acc.concat(xs.map(f)), [])
|
return this.reduce((acc, f) => acc.concat(xs.map(f)), [])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -701,16 +703,16 @@ Make array a setoid:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
Array.prototype.equals = function (arr) {
|
Array.prototype.equals = function (arr) {
|
||||||
const len = this.length
|
const len = this.length
|
||||||
if (len !== arr.length) {
|
if (len !== arr.length) {
|
||||||
return false
|
return false
|
||||||
}
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
if (this[i] !== arr[i]) {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
for (let i = 0; i < len; i++) {
|
||||||
return true
|
if (this[i] !== arr[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
;[1, 2].equals([1, 2]) // true
|
;[1, 2].equals([1, 2]) // true
|
||||||
|
|
@ -773,27 +775,29 @@ __Further reading__
|
||||||
* [Mostly Adequate Guide](https://drboolean.gitbooks.io/mostly-adequate-guide/content/ch7.html#whats-your-type)
|
* [Mostly Adequate Guide](https://drboolean.gitbooks.io/mostly-adequate-guide/content/ch7.html#whats-your-type)
|
||||||
* [What is Hindley-Milner?](http://stackoverflow.com/a/399392/22425) on Stack Overflow
|
* [What is Hindley-Milner?](http://stackoverflow.com/a/399392/22425) on Stack Overflow
|
||||||
|
|
||||||
## Union type
|
## Algebraic data type
|
||||||
A union type is the combination of two types together into another one.
|
A composite type made from putting other types together. Two common classes of algebraic types are [sum](#sum-type) and [product](#product-type).
|
||||||
|
|
||||||
JS doesn't have static types but let's say we invent a type `NumOrString` which is a sum of `String` and `Number`.
|
### Sum type
|
||||||
|
A Sum type is the combination of two types together into another one. It is called sum because the number of possible values in the result type is the sum of the input types.
|
||||||
The `+` operator in JS works on strings and numbers so we can use this new type to describe its inputs and outputs:
|
|
||||||
|
|
||||||
|
JavaScript doesn't have types like this but we can use `Set`s to pretend:
|
||||||
```js
|
```js
|
||||||
// add :: (NumOrString, NumOrString) -> NumOrString
|
// imagine that rather than sets here we have types that can only have these values
|
||||||
const add = (a, b) => a + b
|
const bools = new Set([true, false]);
|
||||||
|
const halfTrue = new Set(['half-true']);
|
||||||
|
|
||||||
add(1, 2) // Returns number 3
|
// The weakLogic type contains the sum of the values from bools and halfTrue
|
||||||
add('Foo', 2) // Returns string "Foo2"
|
const weakLogicValues = new Set([...bools, ...halfTrue])
|
||||||
add('Foo', 'Bar') // Returns string "FooBar"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Union types are also known as algebraic types, tagged unions, or sum types.
|
Sum types are sometimes called union types, discriminated unions, or tagged unions.
|
||||||
|
|
||||||
There's a [couple](https://github.com/paldepind/union-type) [libraries](https://github.com/puffnfresh/daggy) in JS which help with defining and using union types.
|
There's a [couple](https://github.com/paldepind/union-type) [libraries](https://github.com/puffnfresh/daggy) in JS which help with defining and using union types.
|
||||||
|
|
||||||
## Product type
|
Flow includes [union types](https://flow.org/en/docs/types/unions/) and TypeScript has [Enums](https://www.typescriptlang.org/docs/handbook/enums.html) to serve the same role.
|
||||||
|
|
||||||
|
### Product type
|
||||||
|
|
||||||
A **product** type combines types together in a way you're probably more familiar with:
|
A **product** type combines types together in a way you're probably more familiar with:
|
||||||
|
|
||||||
|
|
@ -801,12 +805,12 @@ A **product** type combines types together in a way you're probably more familia
|
||||||
// point :: (Number, Number) -> {x: Number, y: Number}
|
// point :: (Number, Number) -> {x: Number, y: Number}
|
||||||
const point = (x, y) => ({x: x, y: y})
|
const point = (x, y) => ({x: x, y: y})
|
||||||
```
|
```
|
||||||
It's called a product because the total possible values of the data structure is the product of the different values.
|
It's called a product because the total possible values of the data structure is the product of the different values. Many languages have a tuple type which is the simplest formulation of a product type.
|
||||||
|
|
||||||
See also [Set theory](https://en.wikipedia.org/wiki/Set_theory).
|
See also [Set theory](https://en.wikipedia.org/wiki/Set_theory).
|
||||||
|
|
||||||
## Option
|
## Option
|
||||||
Option is a [union type](#union-type) with two cases often called `Some` and `None`.
|
Option is a [sum type](#sum-type) with two cases often called `Some` and `None`.
|
||||||
|
|
||||||
Option is useful for composing functions that might not return a value.
|
Option is useful for composing functions that might not return a value.
|
||||||
|
|
||||||
|
|
@ -814,22 +818,22 @@ Option is useful for composing functions that might not return a value.
|
||||||
// Naive definition
|
// Naive definition
|
||||||
|
|
||||||
const Some = (v) => ({
|
const Some = (v) => ({
|
||||||
val: v,
|
val: v,
|
||||||
map (f) {
|
map(f) {
|
||||||
return Some(f(this.val))
|
return Some(f(this.val))
|
||||||
},
|
},
|
||||||
chain (f) {
|
chain(f) {
|
||||||
return f(this.val)
|
return f(this.val)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const None = () => ({
|
const None = () => ({
|
||||||
map (f) {
|
map(f){
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
chain (f) {
|
chain(f){
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// maybeProp :: (String, {a}) -> Option a
|
// maybeProp :: (String, {a}) -> Option a
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue