-
-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathb-monad.js
More file actions
72 lines (58 loc) · 1.6 KB
/
b-monad.js
File metadata and controls
72 lines (58 loc) · 1.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
'use strict';
class Thenable {
constructor(run) {
this.run = run;
}
static of = (v) => new Thenable((res) => res(v));
then = (res, rej) => this.run(res, rej);
map = (fn) => this.chain((v) => Thenable.of(fn(v)));
chain = (fn) =>
new Thenable((res, rej) => this.run((v) => fn(v).then(res, rej), rej));
}
// Tests
const run = (m) => {
const data = { result: null, error: null };
m.then(
(value) => {
data.result = value;
},
(error) => {
data.error = error;
},
);
return data;
};
const eq = (a, b) => a.error === b.error && a.result === b.result;
const assertLaw = (name, left, right) => {
const l = run(left);
const r = run(right);
const ok = eq(l, r);
console.log(name, ok ? 'OK' : 'FAIL', { left: l, right: r });
};
const chain = (m, f) => m.chain(f);
const f = (x) => Thenable.of(x + 1);
const g = (x) => Thenable.of(x * 2);
// 1. Left identity: of(a).chain(f) = f(a)
const testLeftIdentity = () => {
const a = 10;
const left = Thenable.of(a).chain(f);
const right = f(a);
assertLaw('Left identity', left, right);
};
// 2. Right identity: m.chain(of) = m
const testRightIdentity = () => {
const m = Thenable.of(10);
const left = m.chain(Thenable.of);
const right = m;
assertLaw('Right identity', left, right);
};
// 3. Associativity: m.chain(f).chain(g) = m.chain(x => f(x).chain(g))
const testAssociativity = () => {
const m = Thenable.of(10);
const left = chain(chain(m, f), g);
const right = chain(m, (x) => chain(f(x), g));
assertLaw('Associativity', left, right);
};
testLeftIdentity();
testRightIdentity();
testAssociativity();