Skip to content

Commit

Permalink
Flip arguments order in ap
Browse files Browse the repository at this point in the history
  • Loading branch information
rpominov committed Jul 26, 2016
1 parent a6443c9 commit 14eb81c
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 39 deletions.
34 changes: 17 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ method takes one argument:
A value that implements the Apply specification must also
implement the Functor specification.

1. `a.map(f => g => x => f(g(x))).ap(u).ap(v)` is equivalent to `a.ap(u.ap(v))` (composition)
1. `v.ap(u.ap(a.map(f => g => x => f(g(x)))))` is equivalent to `v.ap(u).ap(a)` (composition)

#### `ap` method

Expand All @@ -193,24 +193,24 @@ method takes one argument:

a.ap(b)

1. `a` must be an Apply of a function,
1. `b` must be an Apply of a function,

1. If `a` does not represent a function, the behaviour of `ap` is
1. If `b` does not represent a function, the behaviour of `ap` is
unspecified.

2. `b` must be an Apply of any value
2. `a` must be an Apply of any value

3. `ap` must apply the function in Apply `a` to the value in
Apply `b`
3. `ap` must apply the function in Apply `b` to the value in
Apply `a`

### Applicative

A value that implements the Applicative specification must also
implement the Apply specification.

1. `a.of(x => x).ap(v)` is equivalent to `v` (identity)
2. `a.of(f).ap(a.of(x))` is equivalent to `a.of(f(x))` (homomorphism)
3. `u.ap(a.of(y))` is equivalent to `a.of(f => f(y)).ap(u)` (interchange)
1. `v.ap(a.of(x => x))` is equivalent to `v` (identity)
2. `a.of(x).ap(a.of(f))` is equivalent to `a.of(f(x))` (homomorphism)
3. `a.of(y).ap(u)` is equivalent to `u.ap(a.of(f => f(y)))` (interchange)

#### `of` method

Expand Down Expand Up @@ -265,8 +265,8 @@ Compose.of = function(x) {
return new Compose(F.of(G.of(x)));
};

Compose.prototype.ap = function(x) {
return new Compose(this.c.map(u => y => u.ap(y)).ap(x.c));
Compose.prototype.ap = function(f) {
return new Compose(this.c.ap(f.c.map(u => y => y.ap(u))));
};

Compose.prototype.map = function(f) {
Expand Down Expand Up @@ -399,7 +399,7 @@ The `profunctor` method takes two arguments:
2. `f` can return any value.

2. `g` must be a function which returns a value

1. If `g` is not a function, the behaviour of `promap` is unspecified.
2. `g` can return any value.

Expand All @@ -413,17 +413,17 @@ to implement certain methods then derive the remaining methods. Derivations:
- [`map`][] may be derived from [`ap`][] and [`of`][]:

```js
function(f) { return this.of(f).ap(this); }
function(f) { return this.ap(this.of(f)); }
```

- [`map`][] may be derived from [`chain`][] and [`of`][]:

```js
function(f) { var m = this; return m.chain(a => m.of(f(a))); }
function(f) { return this.chain(a => this.of(f(a))); }
```

- [`map`][] may be derived from [`bimap`]:

```js
function(f) { return this.bimap(a => a, f); }
```
Expand All @@ -437,7 +437,7 @@ to implement certain methods then derive the remaining methods. Derivations:
- [`ap`][] may be derived from [`chain`][]:

```js
function(m) { return this.chain(f => m.map(f)); }
function(m) { return m.chain(f => this.map(f)); }
```

- [`reduce`][] may be derived as follows:
Expand All @@ -454,7 +454,7 @@ to implement certain methods then derive the remaining methods. Derivations:
return this;
};
Const.prototype.ap = function(b) {
return new Const(f(this.value, b.value));
return new Const(f(b.value, this.value));
};
return this.map(x => new Const(x)).sequence(Const.of).value;
}
Expand Down
4 changes: 2 additions & 2 deletions id.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Id.prototype[fl.map] = function(f) {

// Apply
Id.prototype[fl.ap] = function(b) {
return new Id(this.value(b.value));
return new Id(b.value(this.value));
};

// Traversable
Expand Down Expand Up @@ -66,4 +66,4 @@ Id.prototype[fl.extract] = function() {
return this.value;
};

module.exports = Id;
module.exports = Id;
18 changes: 9 additions & 9 deletions laws/applicative.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,33 @@ const {of, ap} = require('..');
### Applicative
1. `a.of(x => x).ap(v)` is equivalent to `v` (identity)
2. `a.of(f).ap(a.of(x))` is equivalent to `a.of(f(x))` (homomorphism)
3. `u.ap(a.of(y))` is equivalent to `a.of(f => f(y)).ap(u)` (interchange)
1. `v.ap(a.of(x => x))` is equivalent to `v` (identity)
2. `a.of(x).ap(a.of(f))` is equivalent to `a.of(f(x))` (homomorphism)
3. `a.of(y).ap(u)` is equivalent to `u.ap(a.of(f => f(y)))` (interchange)
**/

const identityʹ = t => eq => x => {
const a = t[of](identity).ap(t[of](x));
const a = t[of](x)[ap](t[of](identity));
const b = t[of](x);
return eq(a, b);
};

const homomorphism = t => eq => x => {
const a = t[of](identity).ap(t[of](x));
const a = t[of](x)[ap](t[of](identity));
const b = t[of](identity(x));
return eq(a, b);
};

const interchange = t => eq => x => {
const u = t[of](identity);

const a = u.ap(t[of](x));
const b = t[of](thrush(x)).ap(u);
const a = t[of](x)[ap](u);
const b = u[ap](t[of](thrush(x)));
return eq(a, b);
};

module.exports = { identity: identityʹ
, homomorphism
, interchange
};
, interchange
};
8 changes: 4 additions & 4 deletions laws/apply.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ const {of, map, ap} = require('..');
### Apply
1. `a.map(f => g => x => f(g(x))).ap(u).ap(v)` is equivalent to `a.ap(u.ap(v))` (composition)
1. `v.ap(u.ap(a.map(f => g => x => f(g(x)))))` is equivalent to `v.ap(u).ap(a)` (composition)
**/

const composition = t => eq => x => {
const y = t[of](identity);

const a = y[map](compose)[ap](y)[ap](y);
const b = y[ap](y[ap](y));
const a = y[ap](y[ap](y[map](compose)));
const b = y[ap](y)[ap](y);
return eq(a, b);
};

module.exports = { composition };
module.exports = { composition };
12 changes: 5 additions & 7 deletions laws/traversable.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ const {tagged} = require('daggy');

const Compose = tagged('c');
Compose[of] = Compose;
Compose.prototype[ap] = function(x) {
return Compose(this.c.map(u => y => u.ap(y)).ap(x.c));
Compose.prototype[ap] = function(f) {
return Compose(this.c[ap](f.c.map(u => y => y[ap](u))));
};
Compose.prototype[map] = function(f) {
return Compose(this.c[map](y => y[map](f)));
Expand All @@ -22,9 +22,7 @@ Array.prototype[equals] = function(y) {
};
Array.prototype.sequence = function(p) {
return this.reduce((ys, x) => {
return identity(x).map(y => z => {
return z.concat(y);
}).ap(ys);
return ys[ap](identity(x).map(y => z => z.concat(y)));
}, p([]));
};

Expand Down Expand Up @@ -64,5 +62,5 @@ const composition = t => eq => x => {

module.exports = { naturality
, identity: identityʹ
, composition
};
, composition
};

0 comments on commit 14eb81c

Please sign in to comment.