1 | var interfaces = {
|
2 | semigroup: ['concat'],
|
3 | monoid: ['concat', 'empty'],
|
4 | functor: ['map'],
|
5 | apply: ['map', 'ap'],
|
6 | applicative: ['map', 'ap', 'of'],
|
7 | chain: ['map', 'ap', 'chain'],
|
8 | monad: ['map', 'ap', 'chain', 'of'],
|
9 | extend: ['extend']
|
10 | };
|
11 |
|
12 | function correctInterface(type) {
|
13 | return function(obj) {
|
14 | return interfaces[type].every(function(method) {
|
15 | return obj[method] && typeof obj[method] === 'function';
|
16 | });
|
17 | };
|
18 | }
|
19 |
|
20 | function identity(x) { return x; }
|
21 |
|
22 | module.exports = {
|
23 | semigroup: {
|
24 | iface: correctInterface('semigroup'),
|
25 | associative: function(a, b, c) {
|
26 | return a.concat(b).concat(c).equals(a.concat(b.concat(c)));
|
27 | }
|
28 | },
|
29 |
|
30 | functor: {
|
31 | iface: correctInterface('functor'),
|
32 | id: function(obj) {
|
33 | return obj.equals(obj.map(identity));
|
34 | },
|
35 | compose: function(obj, f, g) {
|
36 | return obj.map(function(x) { return f(g(x)); }).equals(
|
37 | obj.map(g).map(f)
|
38 | );
|
39 | }
|
40 | },
|
41 |
|
42 | apply: {
|
43 | iface: correctInterface('apply'),
|
44 | compose: function(a, u, v) {
|
45 | return a.ap(u.ap(v)).equals(
|
46 | a.map(function(f) {
|
47 | return function(g) {
|
48 | return function(x) {
|
49 | return f(g(x));
|
50 | };
|
51 | };
|
52 | }).ap(u).ap(v)
|
53 | );
|
54 | }
|
55 | },
|
56 |
|
57 | applicative: {
|
58 | iface: correctInterface('applicative'),
|
59 | id: function(obj, obj2) {
|
60 | return obj.of(identity).ap(obj2).equals(obj2);
|
61 | },
|
62 | homomorphic: function(obj, f, x) {
|
63 | return obj.of(f).ap(obj.of(x)).equals(obj.of(f(x)));
|
64 | },
|
65 | interchange: function(obj1, obj2, x) {
|
66 | return obj2.ap(obj1.of(x)).equals(
|
67 | obj1.of(function(f) { return f(x); }).ap(obj2)
|
68 | );
|
69 | }
|
70 | },
|
71 |
|
72 | chain: {
|
73 | iface: correctInterface('chain'),
|
74 | associative: function(obj, f, g) {
|
75 | return obj.chain(f).chain(g).equals(
|
76 | obj.chain(function(x) { return f(x).chain(g); })
|
77 | );
|
78 | }
|
79 | },
|
80 |
|
81 | monad: {
|
82 | iface: correctInterface('monad')
|
83 | },
|
84 |
|
85 | extend: {
|
86 | iface: correctInterface('extend')
|
87 | }
|
88 | };
|