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 Sep 6, 2016
1 parent 53e7504 commit 2bbd013
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 33 deletions.
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,37 +175,37 @@ 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

```hs
ap :: Apply f => f (a -> b) ~> f a -> f b
ap :: Apply f => f a ~> f (a -> b) -> f b
```

A value which has an Apply must provide an `ap` method. The `ap`
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 @@ -268,8 +268,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 @@ -470,13 +470,13 @@ 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`]:
Expand All @@ -494,7 +494,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 @@ -511,7 +511,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
2 changes: 1 addition & 1 deletion 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
14 changes: 7 additions & 7 deletions laws/applicative.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,29 @@ 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);
};

Expand Down
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 };
8 changes: 3 additions & 5 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 @@ -25,9 +25,7 @@ Array.prototype[reduce] = Array.prototype.reduce
Array.prototype[concat] = Array.prototype.concat
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

0 comments on commit 2bbd013

Please sign in to comment.