Skip to content

Commit

Permalink
add Maybe type for testing Alternative laws and refactor tests
Browse files Browse the repository at this point in the history
- move patches and test structures into `internal`
  - `Compose` and patching of `Array` form `laws/traversable`
  - `equality`, `Sum` and patching of `String` form `id_test`
  - `Id` from `id`
- rename `id_test` to `test` as it's not just testing `Id` but `Maybe` and `Sum`
  • Loading branch information
safareli committed Oct 28, 2016
1 parent 69655f7 commit 98e3634
Show file tree
Hide file tree
Showing 15 changed files with 276 additions and 152 deletions.
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"/node_modules/",
"/.*",
"/id.js",
"/id_test.js",
"/test.js",
"/implementations.md",
"/logo.png",
"/package.json"
Expand Down
113 changes: 0 additions & 113 deletions id_test.js

This file was deleted.

18 changes: 18 additions & 0 deletions internal/compose.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use strict';

const {tagged} = require('daggy');

const fl = require('..');
const {equality} = require('./func');

const Compose = module.exports = tagged('c');
Compose[fl.of] = Compose;
Compose.prototype[fl.ap] = function(f) {
return Compose(this.c[fl.ap](f.c[fl.map](u => y => y[fl.ap](u))));
};
Compose.prototype[fl.map] = function(f) {
return Compose(this.c[fl.map](y => y[fl.map](f)));
};
Compose.prototype[fl.equals] = function(x) {
return equality(this.c, x.c);
};
8 changes: 8 additions & 0 deletions internal/func.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict';

const fl = require('../');
const equality = (x, y) => typeof x[fl.equals] === 'function' ? x[fl.equals](y) : x === y;

module.exports = {
equality,
};
13 changes: 6 additions & 7 deletions id.js → internal/id.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
'use strict';

const fl = require('./');
const fl = require('../');
const {equality} = require('./func');

const Id = function Id(a) {
this.value = a;
};
const {tagged} = require('daggy');

const Id = module.exports = tagged('value');

// Setoid
Id.prototype[fl.equals] = function(b) {
return typeof this.value[fl.equals] === 'function' ? this.value[fl.equals](b.value) : this.value === b.value;
return equality(this.value, b.value);
};

// Semigroup (value must also be a Semigroup)
Expand Down Expand Up @@ -73,5 +74,3 @@ Id[fl.of] = function(a) {
Id.prototype[fl.extract] = function() {
return this.value;
};

module.exports = Id;
17 changes: 17 additions & 0 deletions internal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

const patch = require('./patch');
const Maybe = require('./maybe');
const Id = require('./id');
const Sum = require('./string_sum');
const Compose = require('./compose');
const {equality} = require('./func');

module.exports = {
Maybe,
Id,
Sum,
Compose,
equality,
patch,
};
50 changes: 50 additions & 0 deletions internal/maybe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use strict';

const {taggedSum} = require('daggy');

const fl = require('..');
const {equality} = require('./func');

const Maybe = module.exports = taggedSum({
Just: ['x'],
Nothing: [],
});

Maybe.prototype[fl.equals] = function(b) {
return this.cata({
Just: x => this.cata({
Just: y => equality(x, y),
Nothing: () => false,
}),
Nothing: () => this.cata({
Just: _ => false,
Nothing: () => true,
}),
});
};

Maybe.prototype[fl.chain] = function(f) {
return this.cata({
Just: x => f(x),
Nothing: () => this,
});
};

Maybe.prototype[fl.ap] = function(m) {
return m[fl.chain](f => this[fl.map](f));
};

Maybe[fl.of] = Maybe.Just;

Maybe.prototype[fl.map] = function(f) {
return this[fl.chain](a => Maybe[fl.of](f(a)));
};

Maybe[fl.zero] = () => Maybe.Nothing;

Maybe.prototype[fl.alt] = function(b) {
return this.cata({
Just: _ => this,
Nothing: () => b,
});
};
19 changes: 19 additions & 0 deletions internal/patch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

const fl = require('..');

module.exports = () => {
String.prototype[fl.concat] = String.prototype.concat;
Array.prototype[fl.equals] = function(y) {
return this.length === y.length && this.join('') === y.join('');
};
Array.prototype[fl.map] = Array.prototype.map;
Array.prototype[fl.reduce] = Array.prototype.reduce;
Array.prototype[fl.concat] = Array.prototype.concat;
Array.prototype[fl.traverse] = function(f, p) {
return this.map(f)[fl.reduce](
(ys, x) => ys[fl.ap](x[fl.map](y => z => z[fl.concat](y))),
p([])
);
};
};
20 changes: 20 additions & 0 deletions internal/string_sum.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';

const {tagged} = require('daggy');

const fl = require('..');
const {equality} = require('./func');

// Special type of sum for the type of string.
const Sum = module.exports = tagged('v');
Sum[fl.of] = Sum;
Sum[fl.empty] = () => Sum('');
Sum.prototype[fl.map] = function(f) {
return Sum(f(this.v));
};
Sum.prototype[fl.concat] = function(x) {
return Sum(this.v + x.v);
};
Sum.prototype[fl.equals] = function(x) {
return equality(this.v, x.v);
};
File renamed without changes.
File renamed without changes.
File renamed without changes.
30 changes: 2 additions & 28 deletions laws/traversable.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,8 @@
'use strict';

const Id = require('../id');
const {Id, Compose} = require('../internal');
const {identity} = require('fantasy-combinators');
const {of, ap, reduce, traverse, map, equals, concat} = require('..');
const {tagged} = require('daggy');

const Compose = tagged('c');
Compose[of] = Compose;
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)));
};
Compose.prototype[equals] = function(x) {
return this.c[equals] ? this.c[equals](x.c) : this.c === x.c;
};

Array.prototype[equals] = function(y) {
return this.length === y.length && this.join('') === y.join('');
};
Array.prototype[map] = Array.prototype.map;
Array.prototype[reduce] = Array.prototype.reduce;
Array.prototype[concat] = Array.prototype.concat;
Array.prototype[traverse] = function(f, p) {
return this.map(f)[reduce](
(ys, x) => ys[ap](x[map](y => z => z[concat](y))),
p([])
);
};
const {of, traverse, map} = require('..');

/**
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@
"url": "https://github.com/fantasyland/fantasy-land.git"
},
"files": [
"id.js",
"index.js",
"internal/*.js",
"laws/*.js"
],
"main": "index.js",
"scripts": {
"lint": "eslint --config node_modules/sanctuary-style/eslint-es6.json --env es6 --env node --rule 'max-len: [off]' -- *.js laws/*.js",
"test": "npm run-script lint && nodeunit id_test.js",
"lint": "eslint --config node_modules/sanctuary-style/eslint-es6.json --env es6 --env node --rule 'max-len: [off]' -- *.js laws/*.js internal/*.js",
"unit": "nodeunit test.js",
"test": "npm run-script lint && npm run-script unit",
"release-major": "xyz --repo [email protected]:fantasyland/fantasy-land.git --increment major",
"release-minor": "xyz --repo [email protected]:fantasyland/fantasy-land.git --increment minor",
"release-patch": "xyz --repo [email protected]:fantasyland/fantasy-land.git --increment patch"
Expand Down
Loading

0 comments on commit 98e3634

Please sign in to comment.