UNPKG

3.65 kBJavaScriptView Raw
1var 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 comonad: ['extend', 'extract'],
11 foldable: ['reduce'],
12 transformer: ['lift']
13};
14
15var Identity = require('..').Identity;
16
17function correctInterface(type) {
18 return function(obj) {
19 return interfaces[type].every(function(method) {
20 return obj[method] && typeof obj[method] === 'function';
21 });
22 };
23}
24
25function identity(x) { return x; }
26
27module.exports = function(eq) {
28 return {
29 semigroup: {
30 iface: correctInterface('semigroup'),
31 associative: function (a, b, c) {
32 return eq(a.concat(b).concat(c), a.concat(b.concat(c)));
33 }
34 },
35
36 functor: {
37 iface: correctInterface('functor'),
38 id: function (obj) {
39 return eq(obj, obj.map(identity));
40 },
41 compose: function (obj, f, g) {
42 return eq(
43 obj.map(function (x) {
44 return f(g(x));
45 }),
46 obj.map(g).map(f)
47 );
48 }
49 },
50
51 apply: {
52 iface: correctInterface('apply'),
53 compose: function (a, u, v) {
54 return eq(
55 a.ap(u.ap(v)),
56 a.map(function (f) {
57 return function (g) {
58 return function (x) {
59 return f(g(x));
60 };
61 };
62 }).ap(u).ap(v)
63 );
64 }
65 },
66
67 applicative: {
68 iface: correctInterface('applicative'),
69 id: function (obj, obj2) {
70 return eq(obj.of(identity).ap(obj2), obj2);
71 },
72 homomorphic: function (obj, f, x) {
73 return eq(obj.of(f).ap(obj.of(x)), obj.of(f(x)));
74 },
75 interchange: function (obj1, obj2, x) {
76 return eq(
77 obj2.ap(obj1.of(x)),
78 obj1.of(function (f) {
79 return f(x);
80 }).ap(obj2)
81 );
82 }
83 },
84
85 chain: {
86 iface: correctInterface('chain'),
87 associative: function (obj, f, g) {
88 return eq(
89 obj.chain(f).chain(g),
90 obj.chain(function (x) {
91 return f(x).chain(g);
92 })
93 );
94 }
95 },
96
97 monad: {
98 iface: correctInterface('monad')
99 },
100
101 extend: {
102 iface: correctInterface('extend'),
103 associative: function(obj, f, g) {
104 return eq(
105 obj.extend(g).extend(f),
106 obj.extend(function(_obj) {
107 return f(_obj.extend(g));
108 })
109 );
110 }
111 },
112
113 comonad: {
114 iface: correctInterface('comonad'),
115 leftIdentity: function (obj) {
116 return eq(obj.extend(function(_obj) { return _obj.extract(); }), obj);
117 },
118 rightIdentity: function (obj, f) {
119 return eq(obj.extend(f).extract(), f(obj));
120 }
121 },
122
123 foldable: {
124 iface: correctInterface('foldable')
125 },
126
127 transformer: {
128 iface: function (T) {
129 return correctInterface('transformer')(T(Identity)) &&
130 correctInterface('monad')(T(Identity)(identity));
131 },
132 id: function (transformer) {
133 var T = transformer(Identity);
134 return eq(T.lift(Identity.of(1)), T.of(1));
135 },
136 associative: function (transformer) {
137 var T = transformer(Identity);
138 var m = Identity(1);
139 var f = function (x) {
140 return Identity(x * x);
141 };
142 return eq(
143 T.lift(m.chain(f)),
144 T.lift(m).chain(function (x) {
145 return T.lift(f(x));
146 })
147 );
148 }
149 }
150 };
151};