forked from baetheus/fun
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathiterable.ts
More file actions
110 lines (98 loc) · 2.18 KB
/
iterable.ts
File metadata and controls
110 lines (98 loc) · 2.18 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
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
import type { Kind, Out } from "./kind.ts";
import type { Monad } from "./monad.ts";
export interface KindIterable extends Kind {
readonly kind: Iterable<Out<this, 0>>;
}
const isIterator = <A>(
o: (() => Iterator<A>) | Generator<A>,
): o is Generator<A> => Object.hasOwn(o, Symbol.iterator);
export function make<A>(
fa: (() => Iterator<A>) | Generator<A>,
): Iterable<A> {
if (isIterator(fa)) {
return fa;
}
return { [Symbol.iterator]: fa };
}
export function range(
count: number,
start = 0,
step = 1,
): Iterable<number> {
return make(function* () {
let index = Math.floor(count);
let value = start;
while (index > 0) {
yield value;
index--;
value += step;
}
});
}
export function of<A>(...a: A[]): Iterable<A> {
return make(function* () {
let index = -1;
const length = a.length;
while (++index < length) {
yield a[index];
}
});
}
export function ap<A>(
ua: Iterable<A>,
): <I>(ufai: Iterable<(a: A) => I>) => Iterable<I> {
return (ufai) =>
make(function* () {
for (const fai of ufai) {
for (const a of ua) {
yield fai(a);
}
}
});
}
export function map<A, I>(fai: (a: A) => I): (ta: Iterable<A>) => Iterable<I> {
return (ta) =>
make(function* () {
for (const a of ta) {
yield fai(a);
}
});
}
export function join<A>(tta: Iterable<Iterable<A>>): Iterable<A> {
return make(function* () {
for (const ta of tta) {
for (const a of ta) {
yield a;
}
}
});
}
export function chain<A, I>(
fati: (a: A) => Iterable<I>,
): (ta: Iterable<A>) => Iterable<I> {
return (ta) =>
make(function* () {
for (const a of ta) {
for (const i of fati(a)) {
yield i;
}
}
});
}
export function forEach<A>(fa: (a: A) => void): (ta: Iterable<A>) => void {
return (ta) => {
for (const a of ta) {
fa(a);
}
};
}
export function reduce<A, O>(foao: (o: O, a: A) => O, o: O) {
return (ua: Iterable<A>): O => {
let out = o;
for (const a of ua) {
out = foao(o, a);
}
return out;
};
}
export const MonadIterable: Monad<KindIterable> = { of, ap, map, join, chain };