/
Maybe.js
89 lines (69 loc) · 2.47 KB
/
Maybe.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
import { assertIsDefined, assertIsNone } from "./asserts.js";
import { factorizeSumType } from "./SumType.js";
const $$value = Symbol.for("TypeValue");
export const Maybe = factorizeSumType(
"Maybe",
{
Nothing: [],
Just: [ $$value ]
}
);
Maybe.fromNullable = value => !assertIsDefined(value) || assertIsNone(value) ? Maybe.nothing() : Maybe.just(value);
Maybe.just = value => Maybe.Just(value);
Maybe.nothing = () => Maybe.Nothing;
Maybe.of = value => Maybe.Just(value);
// alt :: Maybe a ~> Maybe a -> Maybe a
Maybe.prototype.alt = Maybe.prototype["fantasy-land/alt"] = function (container) {
return this.fold({
Just: _ => this,
Nothing: _ => container
});
};
// ap :: Maybe a ~> m (a -> b) -> Maybe b
Maybe.prototype.ap = Maybe.prototype["fantasy-land/ap"] = function (container) {
if (Maybe.Nothing.is(this)) return this;
return container.fold({
Just: _ => Maybe.of(container[$$value](this[$$value])),
Nothing: _ => container
});
};
// chain :: Maybe a ~> (a -> Maybe b) -> Maybe b
Maybe.prototype.chain = Maybe.prototype["fantasy-land/chain"] = function (composedFunction) {
return this.fold({
Just: value => composedFunction(value),
Nothing: _ => Maybe.Nothing
});
};
// filter :: Maybe a ~> (a -> Boolean) -> Maybe a
Maybe.prototype.filter = Maybe.prototype["fantasy-land/filter"] = function (predicate) {
return this.fold({
Just: _ => predicate(this[$$value]) ? this : Maybe.Nothing,
Nothing: _ => this
});
};
// map :: Maybe a ~> (a -> b) -> Maybe b
Maybe.prototype.map = Maybe.prototype["fantasy-land/map"] = function (composedFunction) {
// return this.chain(container => Maybe.of(composedFunction(container)));
return this.fold({
Just: _ => Maybe.of(composedFunction(this[$$value])),
Nothing: _ => this
});
};
// reduce :: Maybe a ~> ((b, a) -> b, b) -> b
Maybe.prototype.reduce = Maybe.prototype["fantasy-land/reduce"] = function (composedFunction, accumulator) {
return this.fold({
Just: _ => composedFunction(accumulator, this[$$value]),
Nothing: _ => accumulator
});
};
Maybe.prototype.sequence = Maybe.prototype["fantasy-land/sequence"] = function (TypeRep) {
return this.traverse(TypeRep, x => x);
};
// traverse :: Applicative f, Traversable t => t a ~> (TypeRep f, a -> f b) -> f (t b)
Maybe.prototype.traverse = function (TypeRep, composedFunction) {
return this.fold({
Just: _ => composedFunction(this[$$value]).map(Maybe.of),
Nothing: _ => TypeRep.of(this)
});
};
export default Maybe;