Skip to content

Commit

Permalink
Add Category spec
Browse files Browse the repository at this point in the history
  • Loading branch information
gabejohnson committed May 16, 2017
1 parent 20f0b76 commit d82076a
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 1 deletion.
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ structures:
* [Setoid](#setoid)
* [Ord](#ord)
* [Semigroupoid](#semigroupoid)
* [Category](#category)
* [Semigroup](#semigroup)
* [Monoid](#monoid)
* [Functor](#functor)
Expand All @@ -31,7 +32,7 @@ structures:
* [Bifunctor](#bifunctor)
* [Profunctor](#profunctor)

<img src="figures/dependencies.png" width="888" height="294" />
<img src="figures/dependencies.png" width="888" height="257" />

## General

Expand Down Expand Up @@ -165,6 +166,32 @@ A value which has a Semigroupoid must provide a `compose` method. The

2. `compose` must return a value of the same Semigroupoid.

### Category

A value that implements the Category specification must also implement
the [Semigroupoid](#semigroupoid) specification.

1. `a.compose(C.id())` is equivalent to `a` (right identity)
2. `C.id().compose(a)` is equivalent to `a` (left identity)

#### `id` method

```hs
id :: Category c => () -> c a a
```

A value which has a Category must provide an `id` function on its
[type representative](#type-representatives):

C.id()

Given a value `c`, one can access its type representative via the
`constructor` property:

c.constructor.id()

1. `id` must return a value of the same Category

### Semigroup

1. `a.concat(b).concat(c)` is equivalent to `a.concat(b.concat(c))` (associativity)
Expand Down
2 changes: 2 additions & 0 deletions figures/dependencies.dot
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ digraph {
Applicative;
Apply;
Bifunctor;
Category;
Chain;
ChainRec;
Comonad;
Expand Down Expand Up @@ -42,5 +43,6 @@ digraph {
Functor -> Traversable;
Plus -> Alternative;
Semigroup -> Monoid;
Semigroupoid -> Category;
Setoid -> Ord;
}
Binary file modified figures/dependencies.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
equals: 'fantasy-land/equals',
lte: 'fantasy-land/lte',
compose: 'fantasy-land/compose',
id: 'fantasy-land/id',
concat: 'fantasy-land/concat',
empty: 'fantasy-land/empty',
map: 'fantasy-land/map',
Expand Down
5 changes: 5 additions & 0 deletions internal/patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,9 @@ module.exports = () => {
return f(g(x));
};
};
Function[fl.id] = function() {
return function(x) {
return x;
};
};
};
26 changes: 26 additions & 0 deletions laws/category.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'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};
6 changes: 6 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const ord = require('./laws/ord');
const plus = require('./laws/plus');
const semigroup = require('./laws/semigroup');
const semigroupoid = require('./laws/semigroupoid');
const category = require('./laws/category');
const setoid = require('./laws/setoid');
const traversable = require('./laws/traversable');

Expand Down Expand Up @@ -52,6 +53,11 @@ 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)),
};
Expand Down

0 comments on commit d82076a

Please sign in to comment.