-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmonads.js
117 lines (103 loc) · 2.48 KB
/
monads.js
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// @flow
const R = require("ramda");
// -- Identities -----------------------------------------------------
class Identity<A: mixed> {
+__value: A;
constructor(x: A) {
this.__value = x;
}
static of(x: A): Identity<A> {
return new Identity(x);
}
map<B: *>(f: (_: A) => B): Identity<B> {
return Identity.of(f(this.__value));
}
join(): A {
return this.__value;
}
toString(): string {
return `Identity(${+this.__value})`;
}
}
// -- Maybe ----------------------------------------------------------
class Maybe<A: *> {
+__value: A;
constructor(x: A) {
this.__value = x;
}
static of(x: A): Maybe<A> {
return new Maybe(x);
}
isNothing(): boolean {
return this.__value === null || this.__value === undefined;
}
map<B: *>(f: (_: A) => B): Maybe<B | null> {
return this.isNothing() ? Maybe.of(null) : Maybe.of(f(this.__value));
}
join(): Maybe<null> | A {
return this.isNothing() ? Maybe.of(null) : this.__value;
}
toString(): string {
return `Maybe(${+this.__value})`;
}
}
const maybe = R.curry(function<A, B>(x: B, f: A => B, m: Maybe<A>) {
return m.isNothing() ? x : f(m.__value);
});
// -- Either ---------------------------------------------------------
class HKT<F, A> {}
type HKT2<F, A, B> = HKT<HKT<F, A>, B>;
class Left<A: *> {
+__value: A;
constructor(x: A) {
this.__value = x;
}
static of(x: A): Left<A> {
return new Left(x);
}
map<B: *>(f: (_: A) => B): Left<A> {
return this;
}
toString(): string {
return `Left(${+this.__value})`;
}
}
class Right<A: *> {
+__value: A;
constructor(x: A) {
this.__value = x;
}
static of(x: A): Right<A> {
return new Right(x);
}
map<B: *>(f: (_: A) => B): Right<B> {
return Right.of(f(this.__value));
}
toString(): string {
return `Right(${+this.__value})`;
}
}
type Either<A, B> = Left<A> | Right<B>;
function either<A, B, C>(f: A => C, g: B => C, e: Either<A, B>): C {
if (e instanceof Left) {
return f(e.__value);
}
return g(e.__value);
}
// -- IO ------------------------------------------------------------
class IO<A: Function> {
+unsafePerformIO: A;
constructor(x: A) {
this.unsafePerformIO = x;
}
static of(x: A): IO<() => A> {
return new IO(() => x);
}
map<B: *>(f: (_: A) => B): IO<() => B> {
return new IO(R.compose(f, this.unsafePerformIO));
}
toString(): string {
return `IO(${+this.unsafePerformIO})`;
}
}
module.exports = { Identity, Maybe, maybe, Right, Left, either, IO };