From db300ff0ce24b66b48ac6b35df19a97dfd6d1142 Mon Sep 17 00:00:00 2001 From: Roman Pominov Date: Tue, 13 Sep 2016 12:36:54 +0300 Subject: [PATCH] Flip arguments order in ap (#145) --- README.md | 32 ++++++++++++++++---------------- id.js | 2 +- laws/applicative.js | 14 +++++++------- laws/apply.js | 8 ++++---- laws/traversable.js | 8 +++----- 5 files changed, 31 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 3b75e54..1d898b5 100644 --- a/README.md +++ b/README.md @@ -175,12 +175,12 @@ 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` @@ -188,24 +188,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 @@ -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) { @@ -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`]: @@ -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: @@ -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; } diff --git a/id.js b/id.js index a9c7e69..9b4e81d 100644 --- a/id.js +++ b/id.js @@ -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 diff --git a/laws/applicative.js b/laws/applicative.js index 442f584..d3ca796 100644 --- a/laws/applicative.js +++ b/laws/applicative.js @@ -7,20 +7,20 @@ 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); }; @@ -28,8 +28,8 @@ const homomorphism = t => eq => x => { 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); }; diff --git a/laws/apply.js b/laws/apply.js index f962025..14bc254 100644 --- a/laws/apply.js +++ b/laws/apply.js @@ -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 }; \ No newline at end of file +module.exports = { composition }; diff --git a/laws/traversable.js b/laws/traversable.js index 53177e4..8042cf7 100644 --- a/laws/traversable.js +++ b/laws/traversable.js @@ -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))); @@ -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([])); };