Skip to content

Commit 77f9117

Browse files
authored
Merge pull request #146 from stevemao/morphisms
Add more morphisms
2 parents feace35 + 05d7e94 commit 77f9117

File tree

1 file changed

+116
-1
lines changed

1 file changed

+116
-1
lines changed

readme.md

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ __Table of Contents__
4949
* [Morphism](#morphism)
5050
* [Endomorphism](#endomorphism)
5151
* [Isomorphism](#isomorphism)
52+
* [Homomorphism](#homomorphism)
53+
* [Catamorphism](#catamorphism)
54+
* [Anamorphism](#anamorphism)
55+
* [Hylomorphism](#hylomorphism)
56+
* [Paramorphism](#paramorphism)
57+
* [Apomorphism](#apomorphism)
5258
* [Setoid](#setoid)
5359
* [Semigroup](#semigroup)
5460
* [Foldable](#foldable)
@@ -182,6 +188,37 @@ add2(10) // 12
182188

183189
```
184190

191+
## Closure
192+
193+
A closure is a way of accessing a variable outside its scope.
194+
Formally, a closure is a technique for implementing lexically scopped named binding. It is a way of storing a function with an environment.
195+
196+
A closure is a scope which captures local variables of a function for access even after the execution has moved out of the block in which it is defined.
197+
ie. they allow referencing a scope after the block in which the variables were declared has finished executing.
198+
199+
200+
```js
201+
const addTo = x => y => x + y;
202+
var addToFive = addTo(5);
203+
addToFive(3); //returns 8
204+
```
205+
The function ```addTo()``` returns a function(internally called ```add()```), lets store it in a variable called ```addToFive``` with a curried call having parameter 5.
206+
207+
Ideally, when the function ```addTo``` finishes execution, its scope, with local variables add, x, y should not be accessible. But, it returns 8 on calling ```addToFive()```. This means that the state of the function ```addTo``` is saved even after the block of code has finished executing, otherwise there is no way of knowing that ```addTo``` was called as ```addTo(5)``` and the value of x was set to 5.
208+
209+
Lexical scoping is the reason why it is able to find the values of x and add - the private variables of the parent which has finished executing. This value is called a Closure.
210+
211+
The stack along with the lexical scope of the function is stored in form of reference to the parent. This prevents the closure and the underlying variables from being garbage collected(since there is at least one live reference to it).
212+
213+
Lambda Vs Closure: A lambda is essentially a function that is defined inline rather than the standard method of declaring functions. Lambdas can frequently be passed around as objects.
214+
215+
A closure is a function that encloses its surrounding state by referencing fields external to its body. The enclosed state remains across invocations of the closure.
216+
217+
218+
__Further reading/Sources__
219+
* [Lambda Vs Closure](http://stackoverflow.com/questions/220658/what-is-the-difference-between-a-closure-and-a-lambda)
220+
* [JavaScript Closures highly voted disucussion](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work)
221+
185222
## Auto Currying
186223
Transforming a function that takes multiple arguments into one that if given less than its correct number of arguments returns a function that takes the rest. When the function gets the correct number of arguments it is then evaluated.
187224

@@ -696,7 +733,85 @@ coordsToPair(pairToCoords([1, 2])) // [1, 2]
696733
pairToCoords(coordsToPair({x: 1, y: 2})) // {x: 1, y: 2}
697734
```
698735

736+
### Homomorphism
737+
738+
A homomorphism is just a structure preserving map. In fact, a functor is just a homomorphism between categories as it preserves the original category's structure under the mapping.
739+
740+
```js
741+
A.of(f).ap(A.of(x)) == A.of(f(x))
742+
743+
Either.of(_.toUpper).ap(Either.of("oreos")) == Either.of(_.toUpper("oreos"))
744+
```
745+
746+
### Catamorphism
747+
748+
A `reduceRight` function that applies a function against an accumulator and each value of the array (from right-to-left) to reduce it to a single value.
749+
750+
```js
751+
const sum = xs => xs.reduceRight((acc, x) => acc + x, 0)
752+
753+
sum([1, 2, 3, 4, 5]) // 15
754+
```
755+
756+
### Anamorphism
757+
758+
An `unfold` function. An `unfold` is the opposite of `fold` (`reduce`). It generates a list from a single value.
759+
760+
```js
761+
const unfold = (f, seed) => {
762+
function go(f, seed, acc) {
763+
const res = f(seed);
764+
return res ? go(f, res[1], acc.concat([res[0]])) : acc;
765+
}
766+
return go(f, seed, [])
767+
}
768+
```
769+
770+
```js
771+
const countDown = n => unfold((n) => {
772+
return n <= 0 ? undefined : [n, n - 1]
773+
}, n)
774+
775+
countDown(5) // [5, 4, 3, 2, 1]
776+
```
777+
778+
### Hylomorphism
779+
780+
The combination of anamorphism and catamorphism.
781+
782+
### Paramorphism
783+
784+
A function just like `reduceRight`. However, there's a difference:
785+
786+
In paramorphism, your reducer's arguments are the current value, the reduction of all previous values, and the list of values that formed that reduction.
787+
788+
```js
789+
// Obviously not safe for lists containing `undefined`,
790+
// but good enough to make the point.
791+
const para = (reducer, accumulator, elements) => {
792+
if (elements.length === 0)
793+
return accumulator
794+
795+
const head = elements[0]
796+
const tail = elements.slice(1)
797+
798+
return reducer(head, tail, para(reducer, accumulator, tail))
799+
}
800+
801+
const suffixes = list => para(
802+
(x, xs, suffxs) => [xs, ... suffxs],
803+
[],
804+
list
805+
)
806+
807+
suffixes([1, 2, 3, 4, 5]) // [[2, 3, 4, 5], [3, 4, 5], [4, 5], [5], []]
808+
```
809+
810+
The third parameter in the reducer (in the above example, `[x, ... xs]`) is kind of like having a history of what got you to your current acc value.
811+
812+
### Apomorphism
699813

814+
it's the opposite of paramorphism, just as anamorphism is the opposite of catamorphism. Whereas with paramorphism, you combine with access to the accumulator and what has been accumulated, apomorphism lets you `unfold` with the potential to return early.
700815

701816
## Setoid
702817

@@ -732,7 +847,7 @@ An object that has a `concat` function that combines it with another object of t
732847

733848
## Foldable
734849

735-
An object that has a `reduce` function that can transform that object into some other type.
850+
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.
736851

737852
```js
738853
const sum = (list) => list.reduce((acc, val) => acc + val, 0)

0 commit comments

Comments
 (0)