Skip to content

Updated Isomorphic and Monad. #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 21, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 103 additions & 13 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ partial(2); //=> 42
> The process of converting a function with multiple arity into the same function with an arity of one. Not to be confused with partial application, which can produce a function with an arity greater than one.

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

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

Expand Down Expand Up @@ -133,13 +133,13 @@ let add = (a, b) => a + b;
// Not points-free - `numbers` is an explicit parameter
let incrementAll = (numbers) => map(add(1))(numbers);

// Points-free - The array is an implicit parameter
// Points-free - The list is an implicit parameter
let incrementAll2 = map(add(1));
```

`total1` lists and uses the parameter `numbers`, so it is not points-free. `total2` is written just by combining functions and values, making no mention of its arguments. It __is__ points-free.
`incrementAll` identifies and uses the parameter `numbers`, so it is not points-free. `incrementAll2` is written just by combining functions and values, making no mention of its arguments. It __is__ points-free.

It is easy to recognize points-free function definitions; they are the ones that contain no '`function`' keywords and no fat arrows.
Points-free function definitions look just like normal assignments without `function` or `=>`.

---

Expand Down Expand Up @@ -269,12 +269,27 @@ The identity value is empty array `[]`

## Monad

> A monad is a container type that provides two functions, [chain](#chain) and [ap](#applicative-functor). Monads provide an interface for executing a common sequence of commands on a particular kind of value, often one you want to avoid acting on directly. One of the most common monads is the "maybe" or optional value monad, which wraps a value that could be either nothing or something. By using a monad instead of the raw value, you can protect your code from exposure to null values. Likewise, a "state" monad can be used in a parser to algorithmically consume an input string using a repeatable sequence of steps that preserves the current state of the input from operation to operation. Also, since a monad is, by definition, a special kind of functor that also returns a monad, they can be chained together to describe any sequence of operations. In functional languages with lazy evaluation, monads are used where sequence of evaluation is important, such as in I/O. Due to this sequencing utility, they are sometimes referred to as "programmable semicolons."
> A monad is a container type that provides two functions, [chain](#chain) and `of`. Monads provide an interface for executing a common sequence of commands on a particular kind of value, often one you want to avoid acting on directly. One of the most common monads is the "maybe" or optional value monad, which wraps a value that could be either nothing or something. By using a monad instead of the raw value, you can protect your code from exposure to null values. Likewise, a "state" monad can be used in a parser to algorithmically consume an input string using a repeatable sequence of steps that preserves the current state of the input from operation to operation. Also, since a monad is, by definition, a special kind of functor that also returns a monad, they can be chained together to describe any sequence of operations. In functional languages with lazy evaluation, monads are used where sequence of evaluation is important, such as in I/O. Due to this sequencing utility, they are sometimes referred to as "programmable semicolons."

The simplest monad is the Identity monad. It simply wraps a value.

```js
let Identity = v => ({ chain: transform => transform(v) })
let Identity = v => ({
val: v,
chain: transform => transform(this.val),
of: v => this.val
})

// Function that increments value and then wraps with Identity.
let increment = v => Identity(v + 1)

// Use chain to apply function to wrapped values
let incrementIdentity = id => id.chain(increment)

incrementIdentity(Identity(1)) // Identity(2)

//Contrast to using a map, where increment would cause nested Identities
id.map(increment) // Identity(Identity(2))
```

---
Expand All @@ -291,6 +306,25 @@ let Identity = v => ({ chain: transform => transform(v) })

## Comonad

> A container type that has `extract` and `extend` functions.

```js
let CoIdentity = v => ({
val: v,
extract: this.v,
extend: f => f(this)
})
```

Extract takes a value out of a container. Essentially it's the opposite of `of`.
```js
CoIdentity(1).extract() // 1
```

Extend runs a function on the comonad. The function should return the same type as the Comonad.
```js
CoIdentity(1).extend(co => co.extract() + 1) // CoIdentity(2)
```
---

## Applicative Functor
Expand All @@ -309,36 +343,92 @@ let Identity = v => ({ chain: transform => transform(v) })

## Isomorphic

> Two objects are Isomorphic is they satisfy the condition: `compose(to, from) == Identity` and `compose(from, to) == Identity`
> Two objects are Isomorphic is they satisfy the condition: `compose(to, from) == identity` and `compose(from, to) == identity`

```js
const toChars = [].join;
const pairToCoords = (arr) => ({x: arr[0], y: arr[1]})

const fromChars = ''.split;
const coordsToPair = (coords) => [coords.x, coords.y]

fromChars.call(toChars.call([1,2,3])) // [ '1,2,3' ]
coordsToPair(pairToCoords([1, 2])) // [1, 2]

toChars.call(fromChars.call([1,2,3])) // '1,2,3'
pairToCoords(coordsToPair({x: 1, y: 2})) // {x: 1, y: 2}
```

---

## Setoid

> An object that has an `equals` function which can be used to compare other objects of the same type.

Make array a setoid.
```js
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]) // false
```

---

## Semigroup

An object that has a `concat` function that combines it with another object of the same type.

```js
[1].concat([2]) // [1, 2]
```

---

## Foldable

> An object that has a reduce function that can transform that object into some other type.

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

---

## Traversable

---
## Type Signatures

## Comonad
> 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:
```js
// functionName :: firstArgType -> secondArgType -> returnType

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

// increment :: Number -> Number
let increment = x => x + 1
```

If a function accepts another function as an argument it is wrapped in parenthesis.

```js
// call :: (a -> b) -> a -> b
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`.
```js
// map :: (a -> b) -> [a] -> [b]
let map = f => list => list.map(f)
```