diff --git a/README.md b/README.md index c8a2dce..2a7c297 100644 --- a/README.md +++ b/README.md @@ -907,8 +907,8 @@ be equivalent to that of the derivation (or derivations). 2. It's discouraged to overload the specified methods. It can easily result in broken and buggy behaviour. 3. It is recommended to throw an exception on unspecified behaviour. -4. An `Id` container which implements many of the methods is provided in - `internal/id.js`. +4. An `Identity` container which implements many of the methods is provided by + [sanctuary-identity](https://github.com/sanctuary-js/sanctuary-identity). [`ap`]: #ap-method diff --git a/internal/compose.js b/internal/compose.js deleted file mode 100644 index 788079c..0000000 --- a/internal/compose.js +++ /dev/null @@ -1,18 +0,0 @@ -'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); -}; diff --git a/internal/func.js b/internal/func.js deleted file mode 100644 index 50e7754..0000000 --- a/internal/func.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -const fl = require('../'); -const equality = (x, y) => typeof x[fl.equals] === 'function' ? x[fl.equals](y) : x === y; -const lte = (x, y) => { - if (typeof y[fl.lte] === 'function') return y[fl.lte](x); - - const typeX = typeof x; - const typeY = typeof y; - return typeX === typeY && (typeX === 'string' || typeX === 'number') && x <= y; -}; - -module.exports = { - equality, - lte, -}; diff --git a/internal/id.js b/internal/id.js deleted file mode 100644 index 8901b6f..0000000 --- a/internal/id.js +++ /dev/null @@ -1,86 +0,0 @@ -'use strict'; - -const fl = require('../'); -const {equality, lte} = require('./func'); - -const {tagged} = require('daggy'); - -const Id = module.exports = tagged('value'); - -// Setoid -Id.prototype[fl.equals] = function(b) { - return equality(this.value, b.value); -}; - -// Ord -Id.prototype[fl.lte] = function(b) { - return lte(this.value, b.value); -}; - -// Semigroup (value must also be a Semigroup) -Id.prototype[fl.concat] = function(b) { - return new Id(this.value[fl.concat](b.value)); -}; - -// Monoid is not satisfiable since the type lacks a universal empty value - -// Filterable -Id.prototype[fl.filter] = function(pred) { - return new Id(this.value[fl.filter](pred)); -}; - -// Foldable -Id.prototype[fl.reduce] = function(f, acc) { - return f(acc, this.value); -}; - -Id.prototype.toArray = function() { - return [this.value]; -}; - -// Functor -Id.prototype[fl.map] = function(f) { - return new Id(f(this.value)); -}; - -// Apply -Id.prototype[fl.ap] = function(b) { - return new Id(b.value(this.value)); -}; - -// Traversable -Id.prototype[fl.traverse] = function(typeRep, f) { - // the typeRep argument is only provided for types where map might fail. - return f(this.value)[fl.map](Id[fl.of]); -}; - -// Chain -Id.prototype[fl.chain] = function(f) { - return f(this.value); -}; - -// ChainRec -Id[fl.chainRec] = function(f, i) { - const next = v => ({done: false, value: v}); - const done = v => ({done: true, value: v}); - let state = {done: false, value: i}; - while (state.done === false) { - state = f(next, done, state.value).value; - } - return new Id(state.value); -}; - -// Extend -Id.prototype[fl.extend] = function(f) { - return new Id(f(this)); -}; - -// Applicative -Id[fl.of] = function(a) { - return new Id(a); -}; - -// Comonad -Id.prototype[fl.extract] = function() { - return this.value; -}; diff --git a/internal/index.js b/internal/index.js deleted file mode 100644 index b433c21..0000000 --- a/internal/index.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -const patch = require('./patch'); -const Id = require('./id'); -const Sum = require('./sum'); -const Compose = require('./compose'); -const {equality} = require('./func'); - -module.exports = { - Id, - Sum, - Compose, - equality, - patch, -}; diff --git a/internal/patch.js b/internal/patch.js deleted file mode 100644 index 0d03f00..0000000 --- a/internal/patch.js +++ /dev/null @@ -1,48 +0,0 @@ -'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.filter] = function(pred) { - return this.filter(x => pred(x)); - }; - Array.prototype[fl.map] = function(f) { - return this.map(x => f(x)); - }; - Array.prototype[fl.ap] = function(fs) { - return fs[fl.chain](f => this.map(f)); - }; - Array.prototype[fl.chain] = function(f) { - return [].concat(this.map(f)); - }; - Array.prototype[fl.reduce] = function(f, x) { - return this.reduce((x, y) => f(x, y), x); - }; - Array.prototype[fl.concat] = Array.prototype.concat; - Array.prototype[fl.traverse] = function(typeRep, f) { - return this[fl.map](f)[fl.reduce]( - (ys, x) => ys[fl.ap](x[fl.map](y => z => z[fl.concat](y))), - typeRep[fl.of]([]) - ); - }; - Array.prototype[fl.alt] = function(b) { - return this.concat(b); - }; - Array[fl.zero] = () => []; - - Function.prototype[fl.compose] = function(g) { - const f = this; - return function(x) { - return f(g(x)); - }; - }; - Function[fl.id] = function() { - return function(x) { - return x; - }; - }; -}; diff --git a/internal/sum.js b/internal/sum.js deleted file mode 100644 index 83053dc..0000000 --- a/internal/sum.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -const {tagged} = require('daggy'); - -const fl = require('..'); -const {equality} = require('./func'); - -const Sum = module.exports = tagged('v'); - -Sum[fl.of] = Sum; -Sum[fl.empty] = () => Sum(0); -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); -}; -Sum.prototype[fl.invert] = function() { - return Sum(this.v >= 0 ? -Math.abs(this.v) : Math.abs(this.v)); -}; diff --git a/laws/alt.js b/laws/alt.js deleted file mode 100644 index b09c80d..0000000 --- a/laws/alt.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -const {alt, map} = require('..'); - -/** - -### Alt - -1. `a.alt(b).alt(c)` is equivalent to `a.alt(b.alt(c))` (associativity) -2. `a.alt(b).map(f)` is equivalent to `a.map(f).alt(b.map(f))` (distributivity) - -**/ - -const associativity = eq => a => b => c => eq( - a[alt](b)[alt](c), - a[alt](b[alt](c)) -); - -const distributivity = eq => a => b => f => eq( - a[alt](b)[map](f), - a[map](f)[alt](b[map](f)) -); - -module.exports = {associativity, distributivity}; diff --git a/laws/alternative.js b/laws/alternative.js deleted file mode 100644 index 39cad12..0000000 --- a/laws/alternative.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -const {alt, zero, ap} = require('..'); - -/** - -### Alternative - -1. `x.ap(f.alt(g))` is equivalent to `x.ap(f).alt(x.ap(g))` (distributivity) -1. `x.ap(M.zero())` is equivalent to `M.zero()` (annihilation) - -**/ - -const distributivity = eq => x => f => g => eq( - x[ap](f[alt](g)), - x[ap](f)[alt](x[ap](g)) -); - -const annihilation = T => eq => x => eq( - x[ap](T[zero]()), - T[zero]() -); - -module.exports = {distributivity, annihilation}; diff --git a/laws/applicative.js b/laws/applicative.js deleted file mode 100644 index d003cb8..0000000 --- a/laws/applicative.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -const {identity, thrush} = require('fantasy-combinators'); -const {of, ap} = require('..'); - -/** - -### Applicative - -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](x)[ap](T[of](identity)); - const b = T[of](x); - return eq(a, b); -}; - -const homomorphism = T => eq => 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 = T[of](x)[ap](u); - const b = u[ap](T[of](thrush(x))); - return eq(a, b); -}; - -module.exports = {identity: identityʹ, homomorphism, interchange}; diff --git a/laws/apply.js b/laws/apply.js deleted file mode 100644 index 999e8ec..0000000 --- a/laws/apply.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -const {identity, compose} = require('fantasy-combinators'); -const {of, map, ap} = require('..'); - -/** - -### Apply - -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[ap](y[ap](y[map](compose))); - const b = y[ap](y)[ap](y); - return eq(a, b); -}; - -module.exports = {composition}; diff --git a/laws/bifunctor.js b/laws/bifunctor.js deleted file mode 100644 index f680cf7..0000000 --- a/laws/bifunctor.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -const {identity, compose} = require('fantasy-combinators'); -const {bimap} = require('..'); - -/** -### Bifunctor - -1. `p.bimap(a =>, b => b)` is equivalent to `p` (identity) -2. `p.bimap(compose(f1)(f2), compose(g1)(g2))` is equivalent to `p.bimap(f1, g1).bimap(f2, g2)` (composition) - -**/ - -const identityʹ = t => eq => x => { - const a = t(x)[bimap](identity, identity); - const b = t(x); - return eq(a, b); -}; - -const composition = t => eq => x => { - const a = t(x)[bimap](compose(identity)(identity), compose(identity)(identity)); - const b = t(x)[bimap](identity, identity)[bimap](identity, identity); - return eq(a, b); -}; - -module.exports = {identity: identityʹ, composition}; diff --git a/laws/category.js b/laws/category.js deleted file mode 100644 index 422bdb8..0000000 --- a/laws/category.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -const {compose, id} = require('..'); - -/** - - ### Category - - 1. `a.compose(C.id())` is equivalent to `a` (right identity) - 2. `C.id().compose(a)` is equivalent to `a` (left identity) - -**/ - -const leftIdentity = f => eq => x => { - const a = f[compose](Function[id]())(x); - const b = f(x); - return eq(a, b); -}; - -const rightIdentity = f => eq => x => { - const a = Function[id]()[compose](f)(x); - const b = f(x); - return eq(a, b); -}; - -module.exports = {leftIdentity, rightIdentity}; diff --git a/laws/chain.js b/laws/chain.js deleted file mode 100644 index 4e6dc0d..0000000 --- a/laws/chain.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -const {of, chain} = require('..'); - -/** - -### 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); -}; - -module.exports = {associativity}; diff --git a/laws/chainrec.js b/laws/chainrec.js deleted file mode 100644 index 8ac4106..0000000 --- a/laws/chainrec.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -const {chain, map, chainRec} = require('..'); - -/** - -### ChainRec - -1. `M.chainRec((next, done, v) => p(v) ? d(v).map(done) : n(v).map(next), i)` - is equivalent to - `(function step(v) { return p(v) ? d(v) : n(v).chain(step); }(i))` - (equivalence) -**/ - -const equivalence = T => eq => p => d => n => x => { - const a = T[chainRec]((next, done, v) => p(v) ? d(v)[map](done) : n(v)[map](next), x); - const b = (function step(v) { return p(v) ? d(v) : n(v)[chain](step); }(x)); - return eq(a, b); -}; - -module.exports = {equivalence}; diff --git a/laws/comonad.js b/laws/comonad.js deleted file mode 100644 index f56ece1..0000000 --- a/laws/comonad.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -const {identity} = require('fantasy-combinators'); -const {extend, extract} = require('..'); - -/** - -### Comonad - -1. `w.extend(_w => _w.extract())` is equivalent to `w` -2. `w.extend(f).extract()` is equivalent to `f(w)` - -**/ - -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); -}; - -module.exports = {leftIdentity, rightIdentity}; diff --git a/laws/contravariant.js b/laws/contravariant.js deleted file mode 100644 index ffcfb1a..0000000 --- a/laws/contravariant.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -const {identity, compose} = require('fantasy-combinators'); -const {contramap} = require('..'); - -/* - -### Contravariant Functor - -1. `u.contramap(a => a)` is equivalent to `u` (identity) -2. `u.contramap(x => f(g(x)))` is equivalent to `u.contramap(f).contramap(g)` (composition) - -*/ - -const identityʹ = t => eq => x => { - const a = t(x)[contramap](identity); - const b = t(x); - return eq(a, b); -}; - -const composition = t => eq => x => { - const a = t(x)[contramap](compose(identity)(identity)); - const b = t(x)[contramap](identity)[contramap](identity); - return eq(a, b); -}; - -module.exports = {identity: identityʹ, composition}; diff --git a/laws/extend.js b/laws/extend.js deleted file mode 100644 index 310cc7b..0000000 --- a/laws/extend.js +++ /dev/null @@ -1,20 +0,0 @@ -'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}; diff --git a/laws/filterable.js b/laws/filterable.js deleted file mode 100644 index e932df4..0000000 --- a/laws/filterable.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -const {filter} = require('..'); - -/** - -### Filterable - -1. `v.filter(x => p(x) && q(x))` is equivalent to `v.filter(p).filter(q)` (distributivity) -2. `v.filter(x => true)` is equivalent to `v` (identity) -3. `v.filter(x => false)` is equivalent to `w.filter(x => false)` - if `v` and `w` are values of the same Filterable (annihilation) - -**/ - -const distributivity = eq => v => p => q => { - const a = v[filter](x => p(x) && q(x)); - const b = v[filter](p)[filter](q); - return eq(a, b); -}; - -const identity = eq => v => { - const a = v[filter](x => true); - const b = v; - return eq(a, b); -}; - -const annihilation = eq => v => w => { - const a = v[filter](x => false); - const b = w[filter](x => false); - return eq(a, b); -}; - -module.exports = {distributivity, identity, annihilation}; diff --git a/laws/foldable.js b/laws/foldable.js deleted file mode 100644 index 2c1b895..0000000 --- a/laws/foldable.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -const {identity} = require('fantasy-combinators'); -const {reduce} = require('..'); - -/** - -### Foldable - -1. `u.reduce` is equivalent to `u.toArray().reduce` - -**/ - -const associativity = t => eq => x => { - const a = t(x)[reduce](identity, x); - const b = t(x).toArray()[reduce](identity, x); - return eq(a, b); -}; - -module.exports = {associativity}; diff --git a/laws/functor.js b/laws/functor.js deleted file mode 100644 index 7d88c8f..0000000 --- a/laws/functor.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -const {map} = require('..'); - -/** - -### 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 = of => eq => x => { - const a = of(x)[map](x => x); - const b = of(x); - return eq(a, b); -}; - -const composition = of => eq => f => g => x => { - const a = of(x)[map](x => f(g(x))); - const b = of(x)[map](g)[map](f); - return eq(a, b); -}; - -module.exports = {identity, composition}; diff --git a/laws/group.js b/laws/group.js deleted file mode 100644 index 9410157..0000000 --- a/laws/group.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -const {of, empty, concat, invert} = require('..'); - -/** - -### Group - -1. `g.concat(g.invert())` is equivalent to `g.empty()` (right inverse) -2. `g.invert().concat(g)` is equivalent to `g.empty()` (left inverse) - -**/ - -const rightInverse = T => eq => x => { - const g = T[of](x); - - const a = g[concat](g[invert]()); - const b = T[empty](); - return eq(a, b); -}; - -const leftInverse = T => eq => x => { - const g = T[of](x); - - const a = g[invert]()[concat](g); - const b = T[empty](); - return eq(a, b); -}; - -module.exports = {rightInverse, leftInverse}; diff --git a/laws/monad.js b/laws/monad.js deleted file mode 100644 index 678a4ac..0000000 --- a/laws/monad.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -const {of, chain} = require('..'); - -/** - -### 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 => f => x => { - const a = t[of](x)[chain](f); - const b = f(x); - return eq(a, b); -}; - -const rightIdentity = t => eq => x => { - const a = t[of](x)[chain](t[of]); - const b = t[of](x); - return eq(a, b); -}; - -module.exports = {leftIdentity, rightIdentity}; diff --git a/laws/monoid.js b/laws/monoid.js deleted file mode 100644 index f1f03ca..0000000 --- a/laws/monoid.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -const {of, empty, concat} = require('..'); - -/** - -### 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[of](x)[concat](T[empty]()); - const b = T[of](x); - return eq(a, b); -}; - -const leftIdentity = T => eq => x => { - const a = T[empty]()[concat](T[of](x)); - const b = T[of](x); - return eq(a, b); -}; - -module.exports = {rightIdentity, leftIdentity}; diff --git a/laws/ord.js b/laws/ord.js deleted file mode 100644 index 81db277..0000000 --- a/laws/ord.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -const {lte, equals} = require('..'); - -/** - ### Ord - - 1. `a.lte(b)` or `b.lte(a)` (totality) - 2. If `a.lte(b)` and `b.lte(a)`, then `a.equals(b)` (antisymmetry) - 3. If `a.lte(b)` and `b.lte(c)`, then `a.lte(c)` (transitivity) - -**/ - -const totality = eq => f => g => { - const a = f[lte](g); - const b = g[lte](f); - const c = true; - return eq(a || b, c); -}; - -const antisymmetry = eq => f => g => { - const a = f[lte](g); - const b = g[lte](f); - const c = f[equals](g); - const d = true; - return eq(a, d) && eq(b, d) && eq(c, d); -}; - -const transitivity = eq => f => g => h => { - const a = f[lte](g); - const b = g[lte](h); - const c = f[lte](h); - const d = true; - return eq(a, d) && eq(b, d) && eq(c, d); -}; - -module.exports = {totality, antisymmetry, transitivity}; diff --git a/laws/plus.js b/laws/plus.js deleted file mode 100644 index 0ecb662..0000000 --- a/laws/plus.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -const {zero, alt, map} = require('..'); - -/** - -### Alt - -1. `x.alt(A.zero())` is equivalent to `x` (right identity) -2. `A.zero().alt(x)` is equivalent to `x` (left identity) -2. `A.zero().map(f)` is equivalent to `A.zero()` (annihilation) - -**/ - -const rightIdentity = T => eq => x => eq( - T[zero]()[alt](x), - x -); - -const leftIdentity = T => eq => x => eq( - x[alt](T[zero]()), - x -); - -const annihilation = T => eq => f => eq( - T[zero]()[map](f), - T[zero]() -); - -module.exports = {rightIdentity, leftIdentity, annihilation}; diff --git a/laws/profunctor.js b/laws/profunctor.js deleted file mode 100644 index 128cbc5..0000000 --- a/laws/profunctor.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -const {identity, compose} = require('fantasy-combinators'); -const {promap} = require('..'); - -/** -### Profunctor - -1. `p.promap(a => a, b => b)` is equivalent to `p` (identity) -2. `p.promap(compose(f1)(f2), compose(g1)(g2))` is equivalent to `p.promap(f1, g1).promap(f2, g2)` (composition) - -**/ - -const identityʹ = t => eq => x => { - const a = t(x)[promap](identity, identity); - const b = t(x); - return eq(a, b); -}; - -const composition = t => eq => x => { - const a = t(x)[promap](compose(identity)(identity), compose(identity)(identity)); - const b = t(x)[promap](identity, identity)[promap](identity, identity); - return eq(a, b); -}; - -module.exports = {identity: identityʹ, composition}; diff --git a/laws/semigroup.js b/laws/semigroup.js deleted file mode 100644 index d2a85d3..0000000 --- a/laws/semigroup.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -const {concat} = require('..'); - -/** - -### 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); - - const a = f[concat](g)[concat](h); - const b = f[concat](g[concat](h)); - return eq(a, b); -}; - -module.exports = {associativity}; diff --git a/laws/semigroupoid.js b/laws/semigroupoid.js deleted file mode 100644 index 325b109..0000000 --- a/laws/semigroupoid.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -const {compose} = require('..'); - -/** - - ### Semigroupoid - - 1. `a.compose(b).compose(c)` is equivalent to `a.compose(b.compose(c))` (associativity) - -**/ - -const associativity = f => g => h => eq => x => { - const a = f[compose](g)[compose](h)(x); - const b = f[compose](g[compose](h))(x); - return eq(a, b); -}; - -module.exports = {associativity}; diff --git a/laws/setoid.js b/laws/setoid.js deleted file mode 100644 index 740bee3..0000000 --- a/laws/setoid.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; - -const {equals} = require('..'); - -/** - -### Setoid - -1. `a.equals(a) === true` (reflexivity) -2. `a.equals(b) === b.equals(a)` (symmetry) -3. If `a.equals(b)` and `b.equals(c)`, then `a.equals(c)` (transitivity) - -**/ - -const reflexivity = t => eq => x => { - const y = t(x); - - const a = y[equals](y); - const b = true; - return eq(a, b); -}; - -const symmetry = t => eq => x => { - const f = t(x); - const g = t(x); - - const a = f[equals](g); - const b = g[equals](f); - return eq(a, b); -}; - -const transitivity = t => eq => x => { - const f = t(x); - const g = t(x); - const h = t(x); - - const a = f[equals](g); - const b = g[equals](h); - const c = f[equals](h); - return eq(a && b, c); -}; - -module.exports = {reflexivity, symmetry, transitivity}; diff --git a/laws/traversable.js b/laws/traversable.js deleted file mode 100644 index 6b0a1cb..0000000 --- a/laws/traversable.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; - -const {Id, Compose} = require('../internal'); -const {identity} = require('fantasy-combinators'); -const {of, traverse, map} = require('..'); - -/** - -### Traversable - -1. `t(u.traverse(F, x => x))` is equivalent to `u.traverse(G, t)` for any - `t` such that `t(a).map(f)` is equivalent to `t(a.map(f))` (naturality) - -2. `u.traverse(F, F.of)` is equivalent to `F.of(u)` for any Applicative `F` - (identity) - -3. `u.traverse(Compose, x => new Compose(x))` is equivalent to - `new Compose(u.traverse(F, x => x).map(x => x.traverse(G, x => x)))` for - `Compose` defined below and any Applicatives `F` and `G` (composition) - -**/ - -const naturality = T => t => eq => x => { - const a = identity(t(x)[traverse](T, y => y)); - const b = t(x)[traverse](T, identity); - return eq(a, b); -}; - -const identityʹ = T => eq => x => { - const u = [x]; - - const a = u[traverse](T, T[of]); - const b = T[of](u); - return eq(a, b); -}; - -const composition = T => t => eq => x => { - const a = t(x)[traverse](Compose, Compose); - const b = Compose(t(x)[traverse](Id, y => y)[map](x => x[traverse](Id, y => y))); - return eq(a, b); -}; - -module.exports = {naturality, identity: identityʹ, composition}; diff --git a/package.json b/package.json index 4941fc0..5922e82 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,9 @@ "issues": { "url": "https://github.com/fantasyland/fantasy-land/issues" }, - "dependencies": { - "daggy": "0.0.x", - "fantasy-combinators": "0.0.x" - }, + "dependencies": {}, "devDependencies": { "eslint": "3.8.x", - "nodeunit": "0.9.x", "sanctuary-style": "0.2.x", "xyz": "2.0.x" }, @@ -33,15 +29,12 @@ "url": "https://github.com/fantasyland/fantasy-land.git" }, "files": [ - "index.js", - "internal/*.js", - "laws/*.js" + "index.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 internal/*.js", - "unit": "nodeunit test.js", - "test": "npm run-script lint && npm run-script unit", + "lint": "eslint --config node_modules/sanctuary-style/eslint-es6.json --env es6 --env node --rule 'max-len: [off]' -- *.js", + "test": "npm run lint", "release-major": "xyz --repo git@github.com:fantasyland/fantasy-land.git --increment major", "release-minor": "xyz --repo git@github.com:fantasyland/fantasy-land.git --increment minor", "release-patch": "xyz --repo git@github.com:fantasyland/fantasy-land.git --increment patch" diff --git a/test.js b/test.js deleted file mode 100644 index 1968dad..0000000 --- a/test.js +++ /dev/null @@ -1,146 +0,0 @@ -'use strict'; - -const fl = require('.'); -const {Id, equality, Sum, patch} = require('./internal'); -patch(); - -const alt = require('./laws/alt'); -const alternative = require('./laws/alternative'); -const applicative = require('./laws/applicative'); -const apply = require('./laws/apply'); -const category = require('./laws/category'); -const chain = require('./laws/chain'); -const chainRec = require('./laws/chainrec'); -const comonad = require('./laws/comonad'); -const extend = require('./laws/extend'); -const filterable = require('./laws/filterable'); -const foldable = require('./laws/foldable'); -const functor = require('./laws/functor'); -const group = require('./laws/group'); -const monad = require('./laws/monad'); -const monoid = require('./laws/monoid'); -const ord = require('./laws/ord'); -const plus = require('./laws/plus'); -const semigroup = require('./laws/semigroup'); -const semigroupoid = require('./laws/semigroupoid'); -const setoid = require('./laws/setoid'); -const traversable = require('./laws/traversable'); - -const test = f => t => { - t.ok(f('x') === true); - t.done(); -}; - -exports.alt = { - associativity: test(x => alt.associativity(equality)(Array[fl.zero]())([x])(Array[fl.zero]())), - distributivity: test(x => alt.distributivity(equality)(Array[fl.zero]())([x])(a => [a])), -}; - -exports.alternative = { - distributivity: test( - x => alternative.distributivity(equality)([x])(Array[fl.zero]())([a => [a]]) - ), - annihilation: test( - x => alternative.annihilation(Array)(equality)([x]) - ), -}; - -exports.applicative = { - identity: test(applicative.identity(Id)(equality)), - homomorphism: test(applicative.homomorphism(Id)(equality)), - interchange: test(applicative.interchange(Id)(equality)), -}; - -exports.apply = { - composition: test(apply.composition(Id)(equality)), -}; - -exports.category = { - leftIdentity: test(category.leftIdentity(x => x + 1)(equality)), - rightIdentity: test(category.rightIdentity(x => x + 1)(equality)), -}; - -exports.chain = { - associativity: test(chain.associativity(Id)(equality)), -}; - -exports.chainRec = { - equivalence: test(x => { - const predicate = a => a.length > 5; - const done = Id[fl.of]; - const next = a => Id[fl.of](a[fl.concat]([x])); - const initial = [x]; - return chainRec.equivalence(Id)(equality)(predicate)(done)(next)(initial); - }), -}; - -exports.comonad = { - leftIdentity: test(comonad.leftIdentity(Id[fl.of])(equality)), - rightIdentity: test(comonad.rightIdentity(Id[fl.of])(equality)), -}; - -exports.extend = { - associativity: test(extend.associativity(Id[fl.of])(equality)), -}; - -exports.filterable = { - distributivity: test(x => filterable.distributivity(equality)(Id[fl.of]([0, 1, 2, 3, 4]))(x => x % 2 === 0)(x => x > 0)), - identity: test(x => filterable.identity(equality)(Id[fl.of]([1, 2, 3]))), - annihilation: test(x => filterable.annihilation(equality)(Id[fl.of]([1, 2, 3]))(Id[fl.of]([4, 5, 6]))), -}; - -exports.foldable = { - associativity: test(foldable.associativity(Id[fl.of])(equality)), -}; - -exports.functor = { - identity: test(functor.identity(Id[fl.of])(equality)), - composition: test(functor.composition(Id[fl.of])(equality)(a => [a, a])(a => [a])), -}; - -exports.group = { - rightInverse: test(() => group.rightInverse(Sum[fl.of])(equality)(42)), - leftInverse: test(() => group.leftInverse(Sum[fl.of])(equality)(42)), -}; - -exports.monad = { - leftIdentity: test(monad.leftIdentity(Id)(equality)(Id[fl.of])), - rightIdentity: test(monad.rightIdentity(Id)(equality)), -}; - -exports.plus = { - rightIdentity: test(x => plus.rightIdentity(Array)(equality)([x])), - leftIdentity: test(x => plus.leftIdentity(Array)(equality)([x])), - annihilation: test(x => plus.annihilation(Array)(equality)(a => [a])), -}; - -exports.monoid = { - leftIdentity: test(() => monoid.leftIdentity(Sum)(equality)(23)), - rightIdentity: test(() => monoid.rightIdentity(Sum)(equality)(23)), -}; - -exports.ord = { - totality: test(() => ord.totality(equality)(Id[fl.of](1))(Id[fl.of](2))), - antisymmetry: test(() => ord.antisymmetry(equality)(Id[fl.of](1))(Id[fl.of](1))), - transitivity: test(() => ord.transitivity(equality)(Id[fl.of](1))(Id[fl.of](2))(Id[fl.of](3))), -}; - -exports.semigroup = { - associativity: test(semigroup.associativity(Id[fl.of])(equality)), -}; - -exports.semigroupoid = { - associativity: test(() => semigroupoid.associativity(x => x + 1)(x => x * x)(x => x - 2)(equality)(5)), -}; - -exports.setoid = { - reflexivity: test(setoid.reflexivity(Id[fl.of])(equality)), - symmetry: test(setoid.symmetry(Id[fl.of])(equality)), - transitivity: test(setoid.transitivity(Id[fl.of])(equality)), -}; - -exports.traversable = { - naturality: test(x => traversable.naturality(Id)(Id[fl.of])(equality)(Id[fl.of](x))), - identity: test(traversable.identity(Id)(equality)), - composition: test(() => traversable.composition(Id)(Id[fl.of])(equality)(Id[fl.of](Sum[fl.of](37)))), -};