Skip to content

Commit

Permalink
Adding some documentation to each file so it's easier to look up
Browse files Browse the repository at this point in the history
 - Code Review changes
 - Verifying the tests
  • Loading branch information
SimonRichardson committed Jan 28, 2016
1 parent b16a872 commit fe92a80
Show file tree
Hide file tree
Showing 16 changed files with 295 additions and 53 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
2 changes: 1 addition & 1 deletion id.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@ Id.prototype[fl.extract] = function() {
return this.value;
};

if (typeof module == 'object') module.exports = Id;
module.exports = Id;
24 changes: 24 additions & 0 deletions id_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict';

const applicative = require('./laws/applicative');
const apply = require('./laws/apply');
const chain = require('./laws/chain');
const comonad = require('./laws/comonad');

const Id = require('./id');

const equality = (x, y) => x.equals(y);

exports.applicative = { identity: t => { t.ok(applicative.identity(Id)(equality)(1)); t.done(); }
, homomorphism: t => { t.ok(applicative.homomorphism(Id)(equality)(1)); t.done(); }
, interchange: t => { t.ok(applicative.interchange(Id)(equality)(1)); t.done(); }
};

exports.apply = { composition: t => { t.ok(apply.composition(Id)(equality)(1)); t.done(); } };

exports.chain = { associativity: t => { t.ok(chain.associativity(Id)(equality)(1)); t.done(); } };

exports.comonad = { leftIdentity: t => { t.ok(comonad.leftIdentity(Id.of)(equality)(1)); t.done(); }
, rightIdentity: t => { t.ok(comonad.rightIdentity(Id.of)(equality)(1)); t.done(); }
, associativity: t => { t.ok(comonad.associativity(Id.of)(equality)(1)); t.done(); }
};
39 changes: 27 additions & 12 deletions laws/applicative.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,39 @@
'use strict';

const {identity, apply} = require('fantasy-combinators');
const {ap} = require('../index');
const {identity, thrush} = require('fantasy-combinators');
const {of, ap} = require('..');

const id = (t) => (eq) => (x) => {
const a = t.of(identity).ap(t.of(x));
const b = t.of(x);
/**
### 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)
**/

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

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

const interchange = (t) => (eq) => (x) => {
const a = t.of(identity).ap(t.of(x));
const b = t.of(apply(t)).ap(t.of(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);
return eq(a, b);
};

modules.exports = { identity: id, homomorphism, interchange };
module.exports = { identity: identityʹ
, homomorphism
, interchange
};
18 changes: 13 additions & 5 deletions laws/apply.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
'use strict';

const {identity, apply} = require('fantasy-combinators');
const {map, ap} = require('../index');
const {identity, compose} = require('fantasy-combinators');
const {of, map, ap} = require('..');

const composition = (t) => (eq) => (x) => {
const y = t(x);
/**
### Apply
1. `a.map(f => g => x => f(g(x))).ap(u).ap(v)` is equivalent to `a.ap(u.ap(v))` (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));
return eq(a, b);
};

modules.exports = { composition };
module.exports = { composition };
18 changes: 13 additions & 5 deletions laws/chain.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
'use strict';

const {chain} = require('../index');
const {of, chain} = require('..');

const associativity = (t) => (eq) => (x) => {
const a = t.of(x)[chain](t.of)[chain](t.of);
const b = t.of(x)[chain]((x) => t.of(x).chain(t.of));
/**
### Chain
1. `m.chain(f).chain(g)` is equivalent to `m.chain(x => f(x).chain(g))` (associativity)
**/

const associativity = t => eq => x => {
const a = t[of](x)[chain](t[of])[chain](t[of]);
const b = t[of](x)[chain]((x) => t[of](x).chain(t[of]));
return eq(a, b);
};

modules.exports = { associativity };
module.exports = { associativity };
37 changes: 37 additions & 0 deletions laws/comonad.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict';

const {identity} = require('fantasy-combinators');
const {extend} = require('..');

/**
### Comonad
1. `w.extend(_w => _w.extract())` is equivalent to `w`
2. `w.extend(f).extract()` is equivalent to `f(w)`
3. `w.extend(f)` is equivalent to `w.extend(x => x).map(f)`
**/

const leftIdentity = t => eq => x => {
const a = t(x).extend(identity).extract();
const b = t(x);
return eq(a, b);
};

const rightIdentity = t => eq => x => {
const a = t(x).extend(w => w.extract());
const b = t(x);
return eq(a, b);
};

const associativity = t => eq => x => {
const a = t(x).extend(identity);
const b = t(x).extend(identity).map(identity);
return eq(a, b);
};

module.exports = { leftIdentity
, rightIdentity
, associativity
};
20 changes: 20 additions & 0 deletions laws/extend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';

const {identity} = require('fantasy-combinators');
const {extend} = require('..');

/**
### Extend
1. `w.extend(g).extend(f)` is equivalent to `w.extend(_w => f(_w.extend(g)))`
**/

const associativity = t => eq => x => {
const a = t(x).extend(identity).extend(identity);
const b = t(x).extend(w => identity(w.extend(identity)));
return eq(a, b);
};

module.exports = { associativity };
17 changes: 17 additions & 0 deletions laws/foldable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

/**
### Foldable
1. `u.reduce` is equivalent to `u.toArray().reduce`
**/

const associativity = t => eq => x => {
const a = t.reduce(identity, x);
const b = t.toArray().reduce(identity, x);
return eq(a, b);
};

module.exports = { associativity };
27 changes: 19 additions & 8 deletions laws/functor.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
'use strict';

const {identity, compose} = require('fantasy-combinators');
const {map} = require('../index');
const {id: identity, compose} = require('fantasy-combinators');
const {map} = require('..');

const id =(t) => (eq) => (x) => {
const a = t(x)[map](identity);
/*
### Functor
1. `u.map(a => a)` is equivalent to `u` (identity)
2. `u.map(x => f(g(x)))` is equivalent to `u.map(g).map(f)` (composition)
*/

const identity = t => eq => x => {
const a = t(x)[map](id);
const b = t(x);
return eq(a, b);
};

const composition = (t) => (eq) => (x) => {
const a = t(x)[map](compose(identity)(identity));
const b = t(x)[map](identity)[map](identity);
const composition = t => eq => x => {
const a = t(x)[map](compose(id)(id));
const b = t(x)[map](id)[map](id);
return eq(a, b);
};

modules.exports = { identity: id, composition };
module.exports = { identity
, composition
};
29 changes: 20 additions & 9 deletions laws/monad.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
'use strict';

const {apply} = require('fantasy-combinators');
const {chain} = require('../index');
const {identity, apply} = require('fantasy-combinators');
const {of_: of, chain} = require('..');

const leftIdentity = (t) => (eq) => (x) => {
const a = t.of(x)[chain](apply(t.of));
const b = apply(t.of)(x);
/**
### Monad
1. `m.of(a).chain(f)` is equivalent to `f(a)` (left identity)
2. `m.chain(m.of)` is equivalent to `m` (right identity)
**/

const leftIdentity = t => eq => x => {
const a = t[of_](x)[chain](identity);
const b = identity(x);
return eq(a, b);
};

const rightIdentity = (t) => (eq) => (x) => {
const a = t.of(x)[chain](t.of);
const b = t.of(x);
const rightIdentity = t => eq => x => {
const a = t[of_](x)[chain](t[of_]);
const b = t[of_](x);
return eq(a, b);
};

modules.exports = { leftIdentity, rightIdentity };
module.exports = { leftIdentity
, rightIdentity
};
19 changes: 15 additions & 4 deletions laws/monoid.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
'use strict';

const {identity, apply} = require('fantasy-combinators');
const {concat} = require('../index');
const {concat} = require('..');

const rightIdentity = (t) => (eq) => (x) => {
/**
### Monoid
1. `m.concat(m.empty())` is equivalent to `m` (right identity)
2. `m.empty().concat(m)` is equivalent to `m` (left identity)
**/

const rightIdentity = t => eq => x => {
const a = t(x)[concat](t.empty());
const b = t(x);
return eq(a, b);
};

const leftIdentity = (t) => (eq) => (x) => {
const leftIdentity = t => eq => x => {
const a = t.empty()[concat](t(x));
const b = t(x);
return eq(a, b);
};

modules.exports = { rightIdentity, leftIdentity };
module.exports = { rightIdentity
, leftIdentity
};
14 changes: 11 additions & 3 deletions laws/semigroup.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
'use strict';

const {identity, apply} = require('fantasy-combinators');
const {concat} = require('../index');
const {concat} = require('..');

const associativity = (t) => (eq) => (x) => {
/**
### Semigroup
1. `a.concat(b).concat(c)` is equivalent to `a.concat(b.concat(c))` (associativity)
**/

const associativity = t => eq => x => {
const f = t(x);
const g = t(x);
const h = t(x);
Expand All @@ -13,4 +21,4 @@ const associativity = (t) => (eq) => (x) => {
return eq(a, b);
};

modules.exports = { associativity };
module.exports = { associativity };
Loading

0 comments on commit fe92a80

Please sign in to comment.