@fncts/io 0.0.34 → 0.0.36
Sign up to get free protection for your applications and to get access to all the features.
- package/Fiber/FiberRuntime.d.ts +7 -7
- package/Fiber/constructors.d.ts +5 -0
- package/IO/api/all.d.ts +41 -0
- package/IO/api/concurrency.d.ts +11 -0
- package/IO/api/interrupt.d.ts +1 -1
- package/IO/api/raceWith.d.ts +2 -1
- package/IO/api.d.ts +7 -2
- package/IO/definition.d.ts +103 -127
- package/IO.d.ts +1 -0
- package/Push/api.d.ts +86 -36
- package/Push/definition.d.ts +28 -13
- package/Push/internal.d.ts +7 -11
- package/RefSubject/Atomic.d.ts +8 -11
- package/RefSubject/Synchronized/definition.d.ts +4 -6
- package/RefSubject/api.d.ts +0 -1
- package/RefSubject/definition.d.ts +6 -8
- package/STM/definition.d.ts +19 -2
- package/Sink/api.d.ts +24 -24
- package/Subject/Atomic.d.ts +4 -6
- package/Subject/definition.d.ts +2 -2
- package/_cjs/Channel/api/runScoped.cjs +1 -1
- package/_cjs/Channel/api/runScoped.cjs.map +1 -1
- package/_cjs/Channel/api.cjs +2 -2
- package/_cjs/Channel/api.cjs.map +1 -1
- package/_cjs/Fiber/FiberRuntime.cjs +110 -98
- package/_cjs/Fiber/FiberRuntime.cjs.map +1 -1
- package/_cjs/Fiber/constructors.cjs +10 -2
- package/_cjs/Fiber/constructors.cjs.map +1 -1
- package/_cjs/Future/api.cjs +1 -1
- package/_cjs/Future/api.cjs.map +1 -1
- package/_cjs/IO/api/all.cjs +33 -0
- package/_cjs/IO/api/all.cjs.map +1 -0
- package/_cjs/IO/api/asyncIO.cjs +1 -1
- package/_cjs/IO/api/asyncIO.cjs.map +1 -1
- package/_cjs/IO/api/bracketExit.cjs +1 -1
- package/_cjs/IO/api/bracketExit.cjs.map +1 -1
- package/_cjs/IO/api/concurrency.cjs +25 -4
- package/_cjs/IO/api/concurrency.cjs.map +1 -1
- package/_cjs/IO/api/disconnect.cjs +1 -1
- package/_cjs/IO/api/disconnect.cjs.map +1 -1
- package/_cjs/IO/api/foreachConcurrent.cjs +1 -1
- package/_cjs/IO/api/foreachConcurrent.cjs.map +1 -1
- package/_cjs/IO/api/foreachExec.cjs +1 -1
- package/_cjs/IO/api/foreachExec.cjs.map +1 -1
- package/_cjs/IO/api/forkIn.cjs +1 -1
- package/_cjs/IO/api/forkIn.cjs.map +1 -1
- package/_cjs/IO/api/forkScoped.cjs +1 -1
- package/_cjs/IO/api/forkScoped.cjs.map +1 -1
- package/_cjs/IO/api/fulfill.cjs +1 -1
- package/_cjs/IO/api/fulfill.cjs.map +1 -1
- package/_cjs/IO/api/interrupt.cjs +18 -6
- package/_cjs/IO/api/interrupt.cjs.map +1 -1
- package/_cjs/IO/api/raceWith.cjs +4 -4
- package/_cjs/IO/api/raceWith.cjs.map +1 -1
- package/_cjs/IO/api/timeout.cjs +8 -5
- package/_cjs/IO/api/timeout.cjs.map +1 -1
- package/_cjs/IO/api/zipConcurrent.cjs +1 -1
- package/_cjs/IO/api/zipConcurrent.cjs.map +1 -1
- package/_cjs/IO/api.cjs +78 -20
- package/_cjs/IO/api.cjs.map +1 -1
- package/_cjs/IO/definition.cjs +14 -191
- package/_cjs/IO/definition.cjs.map +1 -1
- package/_cjs/IO.cjs +11 -0
- package/_cjs/IO.cjs.map +1 -1
- package/_cjs/Layer/MemoMap.cjs +1 -1
- package/_cjs/Layer/MemoMap.cjs.map +1 -1
- package/_cjs/Layer/api.cjs.map +1 -1
- package/_cjs/Push/api.cjs +238 -168
- package/_cjs/Push/api.cjs.map +1 -1
- package/_cjs/Push/definition.cjs +12 -13
- package/_cjs/Push/definition.cjs.map +1 -1
- package/_cjs/Push/internal.cjs +37 -29
- package/_cjs/Push/internal.cjs.map +1 -1
- package/_cjs/RefSubject/Atomic.cjs +15 -19
- package/_cjs/RefSubject/Atomic.cjs.map +1 -1
- package/_cjs/RefSubject/Synchronized/definition.cjs +9 -10
- package/_cjs/RefSubject/Synchronized/definition.cjs.map +1 -1
- package/_cjs/RefSubject/api.cjs +5 -6
- package/_cjs/RefSubject/api.cjs.map +1 -1
- package/_cjs/RefSubject/definition.cjs.map +1 -1
- package/_cjs/STM/api/atomically.cjs +1 -1
- package/_cjs/STM/api/atomically.cjs.map +1 -1
- package/_cjs/STM/api.cjs +2 -2
- package/_cjs/STM/api.cjs.map +1 -1
- package/_cjs/STM/definition.cjs +1 -1
- package/_cjs/STM/definition.cjs.map +1 -1
- package/_cjs/ScopedRef/api.cjs +2 -2
- package/_cjs/ScopedRef/api.cjs.map +1 -1
- package/_cjs/Semaphore.cjs +1 -1
- package/_cjs/Semaphore.cjs.map +1 -1
- package/_cjs/Sink/api.cjs +13 -13
- package/_cjs/Sink/api.cjs.map +1 -1
- package/_cjs/Subject/Atomic.cjs +4 -5
- package/_cjs/Subject/Atomic.cjs.map +1 -1
- package/_cjs/TReentrantLock/api.cjs +2 -2
- package/_cjs/TReentrantLock/api.cjs.map +1 -1
- package/_cjs/TSemaphore/api.cjs +1 -1
- package/_cjs/TSemaphore/api.cjs.map +1 -1
- package/_cjs/collection/immutable/Conc/dropUntilIO.cjs +12 -17
- package/_cjs/collection/immutable/Conc/dropUntilIO.cjs.map +1 -1
- package/_cjs/collection/immutable/Conc/dropWhileIO.cjs +12 -17
- package/_cjs/collection/immutable/Conc/dropWhileIO.cjs.map +1 -1
- package/_cjs/collection/immutable/Conc/filterIO.cjs +2 -12
- package/_cjs/collection/immutable/Conc/filterIO.cjs.map +1 -1
- package/_cjs/collection/immutable/Conc/mapIO.cjs +3 -9
- package/_cjs/collection/immutable/Conc/mapIO.cjs.map +1 -1
- package/_cjs/collection/immutable/Conc/takeWhileIO.cjs +11 -27
- package/_cjs/collection/immutable/Conc/takeWhileIO.cjs.map +1 -1
- package/_mjs/Channel/api/runScoped.mjs +1 -1
- package/_mjs/Channel/api/runScoped.mjs.map +1 -1
- package/_mjs/Channel/api.mjs +2 -2
- package/_mjs/Channel/api.mjs.map +1 -1
- package/_mjs/Fiber/FiberRuntime.mjs +111 -100
- package/_mjs/Fiber/FiberRuntime.mjs.map +1 -1
- package/_mjs/Fiber/constructors.mjs +7 -1
- package/_mjs/Fiber/constructors.mjs.map +1 -1
- package/_mjs/Future/api.mjs +1 -1
- package/_mjs/Future/api.mjs.map +1 -1
- package/_mjs/IO/api/all.mjs +24 -0
- package/_mjs/IO/api/all.mjs.map +1 -0
- package/_mjs/IO/api/asyncIO.mjs +1 -1
- package/_mjs/IO/api/asyncIO.mjs.map +1 -1
- package/_mjs/IO/api/bracketExit.mjs +1 -1
- package/_mjs/IO/api/bracketExit.mjs.map +1 -1
- package/_mjs/IO/api/concurrency.mjs +19 -2
- package/_mjs/IO/api/concurrency.mjs.map +1 -1
- package/_mjs/IO/api/disconnect.mjs +1 -1
- package/_mjs/IO/api/disconnect.mjs.map +1 -1
- package/_mjs/IO/api/foreachConcurrent.mjs +1 -1
- package/_mjs/IO/api/foreachConcurrent.mjs.map +1 -1
- package/_mjs/IO/api/foreachExec.mjs +1 -1
- package/_mjs/IO/api/foreachExec.mjs.map +1 -1
- package/_mjs/IO/api/forkIn.mjs +1 -1
- package/_mjs/IO/api/forkIn.mjs.map +1 -1
- package/_mjs/IO/api/forkScoped.mjs +1 -1
- package/_mjs/IO/api/forkScoped.mjs.map +1 -1
- package/_mjs/IO/api/fulfill.mjs +1 -1
- package/_mjs/IO/api/fulfill.mjs.map +1 -1
- package/_mjs/IO/api/interrupt.mjs +19 -7
- package/_mjs/IO/api/interrupt.mjs.map +1 -1
- package/_mjs/IO/api/raceWith.mjs +4 -4
- package/_mjs/IO/api/raceWith.mjs.map +1 -1
- package/_mjs/IO/api/timeout.mjs +8 -5
- package/_mjs/IO/api/timeout.mjs.map +1 -1
- package/_mjs/IO/api/zipConcurrent.mjs +1 -1
- package/_mjs/IO/api/zipConcurrent.mjs.map +1 -1
- package/_mjs/IO/api.mjs +78 -23
- package/_mjs/IO/api.mjs.map +1 -1
- package/_mjs/IO/definition.mjs +12 -181
- package/_mjs/IO/definition.mjs.map +1 -1
- package/_mjs/IO.mjs +1 -0
- package/_mjs/IO.mjs.map +1 -1
- package/_mjs/Layer/MemoMap.mjs +1 -1
- package/_mjs/Layer/MemoMap.mjs.map +1 -1
- package/_mjs/Layer/api.mjs.map +1 -1
- package/_mjs/Push/api.mjs +223 -166
- package/_mjs/Push/api.mjs.map +1 -1
- package/_mjs/Push/definition.mjs +9 -10
- package/_mjs/Push/definition.mjs.map +1 -1
- package/_mjs/Push/internal.mjs +33 -22
- package/_mjs/Push/internal.mjs.map +1 -1
- package/_mjs/RefSubject/Atomic.mjs +15 -19
- package/_mjs/RefSubject/Atomic.mjs.map +1 -1
- package/_mjs/RefSubject/Synchronized/definition.mjs +9 -10
- package/_mjs/RefSubject/Synchronized/definition.mjs.map +1 -1
- package/_mjs/RefSubject/api.mjs +6 -7
- package/_mjs/RefSubject/api.mjs.map +1 -1
- package/_mjs/RefSubject/definition.mjs.map +1 -1
- package/_mjs/STM/api/atomically.mjs +1 -1
- package/_mjs/STM/api/atomically.mjs.map +1 -1
- package/_mjs/STM/api.mjs +2 -2
- package/_mjs/STM/api.mjs.map +1 -1
- package/_mjs/STM/definition.mjs +1 -1
- package/_mjs/STM/definition.mjs.map +1 -1
- package/_mjs/ScopedRef/api.mjs +2 -2
- package/_mjs/ScopedRef/api.mjs.map +1 -1
- package/_mjs/Semaphore.mjs +1 -1
- package/_mjs/Semaphore.mjs.map +1 -1
- package/_mjs/Sink/api.mjs +10 -10
- package/_mjs/Sink/api.mjs.map +1 -1
- package/_mjs/Subject/Atomic.mjs +4 -5
- package/_mjs/Subject/Atomic.mjs.map +1 -1
- package/_mjs/TReentrantLock/api.mjs +2 -2
- package/_mjs/TReentrantLock/api.mjs.map +1 -1
- package/_mjs/TSemaphore/api.mjs +1 -1
- package/_mjs/TSemaphore/api.mjs.map +1 -1
- package/_mjs/collection/immutable/Conc/dropUntilIO.mjs +12 -17
- package/_mjs/collection/immutable/Conc/dropUntilIO.mjs.map +1 -1
- package/_mjs/collection/immutable/Conc/dropWhileIO.mjs +12 -17
- package/_mjs/collection/immutable/Conc/dropWhileIO.mjs.map +1 -1
- package/_mjs/collection/immutable/Conc/filterIO.mjs +2 -12
- package/_mjs/collection/immutable/Conc/filterIO.mjs.map +1 -1
- package/_mjs/collection/immutable/Conc/mapIO.mjs +3 -9
- package/_mjs/collection/immutable/Conc/mapIO.mjs.map +1 -1
- package/_mjs/collection/immutable/Conc/takeWhileIO.mjs +11 -27
- package/_mjs/collection/immutable/Conc/takeWhileIO.mjs.map +1 -1
- package/_src/Channel/api.ts +3 -3
- package/_src/Fiber/FiberRuntime.ts +76 -75
- package/_src/Fiber/constructors.ts +5 -0
- package/_src/IO/api/all.ts +64 -0
- package/_src/IO/api/concurrency.ts +33 -0
- package/_src/IO/api/foreachExec.ts +2 -2
- package/_src/IO/api/interrupt.ts +20 -7
- package/_src/IO/api/raceWith.ts +4 -2
- package/_src/IO/api/timeout.ts +21 -1
- package/_src/IO/api.ts +79 -27
- package/_src/IO/definition.ts +155 -200
- package/_src/IO.ts +1 -0
- package/_src/Layer/api.ts +0 -1
- package/_src/Push/api.ts +305 -304
- package/_src/Push/definition.ts +19 -17
- package/_src/Push/internal.ts +63 -31
- package/_src/RefSubject/Atomic.ts +16 -22
- package/_src/RefSubject/Synchronized/definition.ts +6 -9
- package/_src/RefSubject/api.ts +9 -12
- package/_src/RefSubject/definition.ts +6 -8
- package/_src/STM/api.ts +0 -5
- package/_src/STM/definition.ts +8 -2
- package/_src/Sink/api.ts +9 -9
- package/_src/Subject/Atomic.ts +6 -8
- package/_src/Subject/definition.ts +2 -2
- package/_src/collection/immutable/Conc/dropUntilIO.ts +18 -15
- package/_src/collection/immutable/Conc/dropWhileIO.ts +18 -17
- package/_src/collection/immutable/Conc/filterIO.ts +1 -11
- package/_src/collection/immutable/Conc/mapIO.ts +2 -9
- package/_src/collection/immutable/Conc/takeWhileIO.ts +19 -28
- package/collection/immutable/Conc/filterIO.d.ts +1 -1
- package/collection/immutable/Conc/mapIO.d.ts +1 -1
- package/collection/immutable/Conc/takeWhileIO.d.ts +1 -1
- package/package.json +2 -2
package/_src/Push/api.ts
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
import type { _A, _E, _R } from "@fncts/base/types";
|
2
|
-
|
3
1
|
import { AtomicReference } from "@fncts/base/internal/AtomicReference";
|
2
|
+
import { IO } from "@fncts/io/IO";
|
3
|
+
import { withExhaust, withSwitch, withUnboundedConcurrency } from "@fncts/io/Push/internal";
|
4
4
|
|
5
|
-
import {
|
6
|
-
import { earlyExit, onEarlyExit } from "./internal.js";
|
5
|
+
import { Push, PushTypeId, PushVariance, Sink } from "./definition.js";
|
7
6
|
|
8
7
|
/**
|
9
8
|
* @tsplus pipeable fncts.io.Push as
|
@@ -14,36 +13,73 @@ export function as<B>(b: Lazy<B>) {
|
|
14
13
|
};
|
15
14
|
}
|
16
15
|
|
16
|
+
interface UnsafeSink<E, A> {
|
17
|
+
event: (value: A) => void;
|
18
|
+
error: (cause: Cause<E>) => void;
|
19
|
+
}
|
20
|
+
|
21
|
+
/**
|
22
|
+
* @tsplus static fncts.io.PushOps asyncInterrupt
|
23
|
+
*/
|
24
|
+
export function asyncInterrupt<R, E, A>(
|
25
|
+
make: (emitter: UnsafeSink<E, A>) => Either<IO<R, never, void>, Push<R, E, A>>,
|
26
|
+
): Push<R, E, A> {
|
27
|
+
return Push<R, E, A>(
|
28
|
+
<R1>(sink: Sink<R | R1, E, A>) =>
|
29
|
+
Do((Δ) => {
|
30
|
+
const future = Δ(Future.make<never, void>());
|
31
|
+
const scope = Δ(IO.scope);
|
32
|
+
const runtime = Δ(IO.runtime<R | R1>());
|
33
|
+
const unsafeSink: UnsafeSink<E, A> = {
|
34
|
+
event: (value) => runtime.unsafeRunOrFork(sink.event(value).forkIn(scope)),
|
35
|
+
error: (cause) => runtime.unsafeRunOrFork(sink.error(cause).fulfill(future).forkIn(scope)),
|
36
|
+
};
|
37
|
+
const eitherPush = Δ(IO(make(unsafeSink)));
|
38
|
+
Δ(
|
39
|
+
eitherPush.match(
|
40
|
+
(canceller) => future.await.onInterrupt(canceller),
|
41
|
+
(push) => push.run(sink),
|
42
|
+
),
|
43
|
+
);
|
44
|
+
}).scoped,
|
45
|
+
);
|
46
|
+
}
|
47
|
+
|
48
|
+
/**
|
49
|
+
* @tsplus static fncts.io.PushOps async
|
50
|
+
*/
|
51
|
+
export function async<E, A>(make: (sink: UnsafeSink<E, A>) => void): Push<never, E, A> {
|
52
|
+
return Push.asyncInterrupt((sink) => {
|
53
|
+
make(sink);
|
54
|
+
return Either.left(IO.unit);
|
55
|
+
});
|
56
|
+
}
|
57
|
+
|
17
58
|
/**
|
18
59
|
* @tsplus static fncts.io.PushOps combineLatest
|
19
60
|
*/
|
20
61
|
export function combineLatest<A extends ReadonlyArray<Push<any, any, any>>>(
|
21
62
|
streams: [...A],
|
22
|
-
): Push<
|
63
|
+
): Push<Push.EnvironmentOf<A[number]>, Push.ErrorOf<A[number]>, { [K in keyof A]: Push.ValueOf<A[K]> }>;
|
23
64
|
export function combineLatest<R, E, A>(streams: Iterable<Push<R, E, A>>): Push<R, E, ReadonlyArray<A>>;
|
24
65
|
export function combineLatest<R, E, A>(streams: Iterable<Push<R, E, A>>): Push<R, E, ReadonlyArray<A>> {
|
25
66
|
return Push((emitter) =>
|
26
67
|
Do((Δ) => {
|
27
68
|
const size = streams.size;
|
28
69
|
const ref: Array<A> = Δ(IO(Array(size)));
|
29
|
-
const latch = Δ(CountdownLatch(size));
|
30
70
|
const emitIfReady = IO(ref.filter((a) => a != null)).flatMap((as) =>
|
31
|
-
as.length === size ? emitter.
|
71
|
+
as.length === size ? emitter.event(as) : IO.unit,
|
32
72
|
);
|
33
73
|
Δ(
|
34
|
-
IO.
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
latch.countDown,
|
42
|
-
),
|
43
|
-
).forkScoped,
|
74
|
+
IO.foreachConcurrent(streams.zipWithIndex, ([i, stream]) =>
|
75
|
+
stream.run(
|
76
|
+
Sink(
|
77
|
+
(value) => IO((ref[i] = value)) > emitIfReady,
|
78
|
+
(cause) => emitter.error(cause),
|
79
|
+
),
|
80
|
+
),
|
44
81
|
),
|
45
82
|
);
|
46
|
-
Δ(latch.await > emitter.end);
|
47
83
|
}),
|
48
84
|
);
|
49
85
|
}
|
@@ -62,28 +98,7 @@ export function combineLatestWith<A, R1, E1, B, C>(that: Push<R1, E1, B>, f: (a:
|
|
62
98
|
*/
|
63
99
|
export function debounce(duration: Lazy<Duration>) {
|
64
100
|
return <R, E, A>(self: Push<R, E, A>): Push<R, E, A> => {
|
65
|
-
return
|
66
|
-
Do((Δ) => {
|
67
|
-
const ref = Δ(Ref.Synchronized.make<Fiber<never, unknown> | null>(null));
|
68
|
-
const latch = Δ(CountdownLatch(1));
|
69
|
-
Δ(
|
70
|
-
self.run(
|
71
|
-
Emitter(
|
72
|
-
(value) =>
|
73
|
-
ref.updateIO((previous) =>
|
74
|
-
Do((Δ) => {
|
75
|
-
Δ(IO.defer(previous ? previous.interrupt : latch.increment));
|
76
|
-
return Δ(IO.acquireRelease(emitter.emit(value).delay(duration), () => latch.countDown).forkScoped);
|
77
|
-
}),
|
78
|
-
),
|
79
|
-
(cause) => emitter.failCause(cause),
|
80
|
-
latch.countDown,
|
81
|
-
),
|
82
|
-
),
|
83
|
-
);
|
84
|
-
Δ(latch.await > emitter.end);
|
85
|
-
}),
|
86
|
-
);
|
101
|
+
return self.switchMapIO((a) => IO.succeedNow(a).delay(duration));
|
87
102
|
};
|
88
103
|
}
|
89
104
|
|
@@ -94,14 +109,90 @@ export function defer<R, E, A>(self: Lazy<Push<R, E, A>>): Push<R, E, A> {
|
|
94
109
|
return Push((emitter) => IO(self).flatMap((push) => push.run(emitter)));
|
95
110
|
}
|
96
111
|
|
112
|
+
/**
|
113
|
+
* @tsplus pipeable fncts.io.Push exhaustMap
|
114
|
+
*/
|
115
|
+
export function exhaustMap<A, R1, E1, B>(f: (a: A) => Push<R1, E1, B>) {
|
116
|
+
return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
|
117
|
+
return Push((sink) => withExhaust((fork) => self.run(Sink((a) => fork(f(a).run(sink)), sink.error))));
|
118
|
+
};
|
119
|
+
}
|
120
|
+
|
121
|
+
/**
|
122
|
+
* @tsplus pipeable fncts.io.Push exhaustMapIO
|
123
|
+
*/
|
124
|
+
export function exhaustMapIO<A, R1, E1, B>(f: (a: A) => IO<R1, E1, B>) {
|
125
|
+
return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
|
126
|
+
return self.exhaustMap((a) => Push.fromIO(f(a)));
|
127
|
+
};
|
128
|
+
}
|
129
|
+
|
130
|
+
/**
|
131
|
+
* @tsplus pipeable fncts.io.Push filterIO
|
132
|
+
*/
|
133
|
+
export function filterIO<A, R1, E1>(predicate: (a: A) => IO<R1, E1, boolean>) {
|
134
|
+
return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, A> => {
|
135
|
+
return Push((sink) =>
|
136
|
+
self.run(
|
137
|
+
Sink(
|
138
|
+
(a) =>
|
139
|
+
predicate(a)
|
140
|
+
.flatMap((b) => (b ? sink.event(a) : IO.unit))
|
141
|
+
.catchAllCause(sink.error),
|
142
|
+
sink.error,
|
143
|
+
),
|
144
|
+
),
|
145
|
+
);
|
146
|
+
};
|
147
|
+
}
|
148
|
+
|
149
|
+
/**
|
150
|
+
* @tsplus pipeable fncts.io.Push filterMapIO
|
151
|
+
*/
|
152
|
+
export function filterMapIO<A, R1, E1, B>(f: (a: A) => IO<R1, E1, Maybe<B>>) {
|
153
|
+
return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
|
154
|
+
return Push((sink) =>
|
155
|
+
self.run(
|
156
|
+
Sink(
|
157
|
+
(a) =>
|
158
|
+
f(a)
|
159
|
+
.flatMap((mb) => mb.match(() => IO.unit, sink.event))
|
160
|
+
.catchAllCause(sink.error),
|
161
|
+
sink.error,
|
162
|
+
),
|
163
|
+
),
|
164
|
+
);
|
165
|
+
};
|
166
|
+
}
|
167
|
+
|
168
|
+
/**
|
169
|
+
* @tsplus pipeable fncts.io.Push filter
|
170
|
+
*/
|
171
|
+
export function filter<A, B extends A>(refinement: Refinement<A, B>): <R, E>(self: Push<R, E, A>) => Push<R, E, B>;
|
172
|
+
export function filter<A>(predicate: Predicate<A>): <R, E>(self: Push<R, E, A>) => Push<R, E, A>;
|
173
|
+
export function filter<A>(predicate: Predicate<A>) {
|
174
|
+
return <R, E>(self: Push<R, E, A>): Push<R, E, A> => {
|
175
|
+
return Push((sink) => self.run(Sink((a) => (predicate(a) ? sink.event(a) : IO.unit), sink.error)));
|
176
|
+
};
|
177
|
+
}
|
178
|
+
|
179
|
+
/**
|
180
|
+
* @tsplus pipeable fncts.io.Push filterMap
|
181
|
+
*/
|
182
|
+
export function filterMap<A, B>(f: (a: A) => Maybe<B>) {
|
183
|
+
return <R, E>(self: Push<R, E, A>): Push<R, E, B> => {
|
184
|
+
return Push((sink) => self.run(Sink((a) => f(a).match(() => IO.unit, sink.event), sink.error)));
|
185
|
+
};
|
186
|
+
}
|
187
|
+
|
97
188
|
/**
|
98
189
|
* @tsplus pipeable fncts.io.Push flatMapConcurrentBounded
|
99
190
|
*/
|
100
191
|
export function flatMapConcurrentBounded<A, R1, E1, B>(f: (a: A) => Push<R1, E1, B>, concurrency: number) {
|
101
192
|
return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
|
102
|
-
return Push(<R2>(emitter:
|
193
|
+
return Push(<R2>(emitter: Sink<R | R1 | R2, E | E1, B>) =>
|
103
194
|
Do((Δ) => {
|
104
|
-
const semaphore = Δ(
|
195
|
+
const semaphore = Δ(Semaphore(concurrency));
|
105
196
|
Δ(self.flatMapConcurrentUnbounded((a) => f(a).transform((io) => semaphore.withPermit(io))).run(emitter));
|
106
197
|
}),
|
107
198
|
);
|
@@ -113,22 +204,7 @@ export function flatMapConcurrentBounded<A, R1, E1, B>(f: (a: A) => Push<R1, E1,
|
|
113
204
|
*/
|
114
205
|
export function flatMapConcurrentUnbounded<A, R1, E1, B>(f: (a: A) => Push<R1, E1, B>) {
|
115
206
|
return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
|
116
|
-
return Push((
|
117
|
-
Do((Δ) => {
|
118
|
-
const latch = Δ(CountdownLatch(1));
|
119
|
-
Δ(
|
120
|
-
self.run(
|
121
|
-
Emitter(
|
122
|
-
(value) =>
|
123
|
-
latch.increment > f(value).run(Emitter(emitter.emit, emitter.failCause, latch.countDown)).forkScoped,
|
124
|
-
emitter.failCause,
|
125
|
-
latch.countDown,
|
126
|
-
),
|
127
|
-
),
|
128
|
-
);
|
129
|
-
Δ(latch.await > emitter.end);
|
130
|
-
}),
|
131
|
-
);
|
207
|
+
return Push((sink) => withUnboundedConcurrency((fork) => self.run(Sink((a) => fork(f(a).run(sink)), sink.error))));
|
132
208
|
};
|
133
209
|
}
|
134
210
|
|
@@ -168,12 +244,11 @@ export function flatten<R, E, R1, E1, A>(self: Push<R, E, Push<R1, E1, A>>): Pus
|
|
168
244
|
* @tsplus static fncts.io.PushOps fromIO
|
169
245
|
*/
|
170
246
|
export function fromIO<R, E, A>(io: Lazy<IO<R, E, A>>): Push<R, E, A> {
|
171
|
-
return Push(
|
172
|
-
(
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
) > emitter.end,
|
247
|
+
return Push((emitter) =>
|
248
|
+
IO.defer(io).matchCauseIO(
|
249
|
+
(cause) => emitter.error(cause),
|
250
|
+
(value) => emitter.event(value),
|
251
|
+
),
|
177
252
|
);
|
178
253
|
}
|
179
254
|
|
@@ -181,17 +256,20 @@ export function fromIO<R, E, A>(io: Lazy<IO<R, E, A>>): Push<R, E, A> {
|
|
181
256
|
* @tsplus static fncts.io.PushOps fromAsyncIterable
|
182
257
|
*/
|
183
258
|
export function fromAsyncIterable<A>(iterable: AsyncIterable<A>): Push<never, never, A> {
|
184
|
-
return Push((
|
259
|
+
return Push(<R>(sink: Sink<R, never, A>) =>
|
260
|
+
IO.asyncIO<R, never, void>((cb) => IO.defer(fromAsyncIterableLoop(iterable[Symbol.asyncIterator](), sink, cb))),
|
261
|
+
);
|
185
262
|
}
|
186
263
|
|
187
264
|
function fromAsyncIterableLoop<A, R>(
|
188
265
|
iterator: AsyncIterator<A>,
|
189
|
-
|
266
|
+
sink: Sink<R, never, A>,
|
267
|
+
cb: (io: UIO<void>) => void,
|
190
268
|
__tsplusTrace?: string,
|
191
269
|
): IO<R, never, void> {
|
192
270
|
return IO.fromPromiseHalt(iterator.next).matchCauseIO(
|
193
|
-
(cause) =>
|
194
|
-
(result) => (result.done ?
|
271
|
+
(cause) => sink.error(cause),
|
272
|
+
(result) => (result.done ? IO(cb(IO.unit)) : sink.event(result.value) > fromAsyncIterableLoop(iterator, sink, cb)),
|
195
273
|
);
|
196
274
|
}
|
197
275
|
|
@@ -199,13 +277,19 @@ function fromAsyncIterableLoop<A, R>(
|
|
199
277
|
* @tsplus static fncts.io.PushOps fromIterable
|
200
278
|
*/
|
201
279
|
export function fromIterable<A>(iterable: Iterable<A>): Push<never, never, A> {
|
202
|
-
return Push((
|
280
|
+
return Push(<R>(sink: Sink<R, never, A>) =>
|
281
|
+
IO.asyncIO<R, never, void>((cb) => IO.defer(fromIterableLoop(iterable[Symbol.iterator](), sink, cb))),
|
282
|
+
);
|
203
283
|
}
|
204
284
|
|
205
|
-
function fromIterableLoop<A, R>(
|
285
|
+
function fromIterableLoop<A, R>(
|
286
|
+
iterator: Iterator<A>,
|
287
|
+
sink: Sink<R, never, A>,
|
288
|
+
cb: (io: UIO<void>) => void,
|
289
|
+
): IO<R, never, void> {
|
206
290
|
return IO.defer(() => {
|
207
291
|
const value = iterator.next();
|
208
|
-
return value.done ?
|
292
|
+
return value.done ? IO(cb(IO.unit)) : sink.event(value.value) > fromIterableLoop(iterator, sink, cb);
|
209
293
|
});
|
210
294
|
}
|
211
295
|
|
@@ -217,12 +301,11 @@ export function multicast<R, E, A>(self: Push<R, E, A>): Push<R, E, A> {
|
|
217
301
|
}
|
218
302
|
|
219
303
|
interface MulticastObserver<E, A> {
|
220
|
-
readonly
|
304
|
+
readonly sink: Sink<any, E, A>;
|
221
305
|
readonly environment: Environment<any>;
|
222
|
-
readonly future: Future<never, void>;
|
223
306
|
}
|
224
307
|
|
225
|
-
export class Multicast<R, E, A> implements Push<R, E, A>,
|
308
|
+
export class Multicast<R, E, A> implements Push<R, E, A>, Sink<never, E, A> {
|
226
309
|
readonly [PushTypeId]: PushTypeId = PushTypeId;
|
227
310
|
declare [PushVariance]: {
|
228
311
|
readonly _R: (_: never) => R;
|
@@ -233,67 +316,59 @@ export class Multicast<R, E, A> implements Push<R, E, A>, Emitter<never, E, A> {
|
|
233
316
|
protected fiber: Fiber<never, unknown> | undefined;
|
234
317
|
constructor(readonly push: Push<R, E, A>) {}
|
235
318
|
|
236
|
-
run<R1>(
|
319
|
+
run<R1>(sink: Sink<R1, E, A>): IO<R | R1, never, void> {
|
237
320
|
return Do((Δ) => {
|
238
321
|
const environment = Δ(IO.environment<R1>());
|
239
|
-
const future = Δ(Future.make<never, void>());
|
240
322
|
Δ(
|
241
323
|
IO.defer(() => {
|
242
|
-
|
243
|
-
if (this.
|
244
|
-
|
245
|
-
} else {
|
246
|
-
return this.push
|
247
|
-
.run(this)
|
248
|
-
.schedule(Schedule.asap)
|
249
|
-
.forkScoped.tap((fiber) => IO((this.fiber = fiber)));
|
324
|
+
let io: URIO<R, void> = IO.unit;
|
325
|
+
if (this.observers.push({ sink: sink, environment }) === 1) {
|
326
|
+
io = this.push.run(this).forkDaemon.flatMap((fiber) => IO((this.fiber = fiber)));
|
250
327
|
}
|
328
|
+
return io > this.fiber!.await.ensuring(this.removeSink(sink));
|
251
329
|
}),
|
252
330
|
);
|
253
|
-
return Δ(future.await);
|
254
331
|
});
|
255
332
|
}
|
256
333
|
|
257
|
-
|
258
|
-
return IO.defer(IO.foreachDiscard(this.observers.slice(), (observer) => this.
|
334
|
+
event(value: A) {
|
335
|
+
return IO.defer(IO.foreachDiscard(this.observers.slice(), (observer) => this.runValue(value, observer)));
|
259
336
|
}
|
260
337
|
|
261
|
-
|
262
|
-
return (
|
263
|
-
IO.defer(IO.foreachDiscard(this.observers.slice(), (observer) => this.runFailCause(cause, observer))) >
|
264
|
-
IO.defer(this.cleanup())
|
265
|
-
);
|
338
|
+
error(cause: Cause<E>) {
|
339
|
+
return IO.defer(IO.foreachDiscard(this.observers.slice(), (observer) => this.runError(cause, observer)));
|
266
340
|
}
|
267
341
|
|
268
|
-
|
269
|
-
return
|
270
|
-
|
271
|
-
|
272
|
-
|
342
|
+
protected runValue(value: A, observer: MulticastObserver<E, A>) {
|
343
|
+
return observer.sink
|
344
|
+
.event(value)
|
345
|
+
.provideEnvironment(observer.environment)
|
346
|
+
.catchAllCause(() => this.removeSink(observer.sink));
|
273
347
|
}
|
274
348
|
|
275
|
-
protected
|
276
|
-
return observer.
|
277
|
-
.
|
278
|
-
.
|
279
|
-
.
|
349
|
+
protected runError(cause: Cause<E>, observer: MulticastObserver<E, A>) {
|
350
|
+
return observer.sink
|
351
|
+
.error(cause)
|
352
|
+
.provideEnvironment(observer.environment)
|
353
|
+
.catchAllCause(() => this.removeSink(observer.sink));
|
280
354
|
}
|
281
355
|
|
282
|
-
protected
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
356
|
+
protected removeSink(sink: Sink<any, E, A>) {
|
357
|
+
return IO.defer(() => {
|
358
|
+
if (this.observers.length === 0) {
|
359
|
+
return IO.unit;
|
360
|
+
}
|
361
|
+
const index = this.observers.findIndex((observer) => observer.sink === sink);
|
362
|
+
if (index > -1) {
|
363
|
+
this.observers.splice(index, 1);
|
364
|
+
if (this.observers.length === 0) {
|
365
|
+
const interrupt = this.fiber!.interrupt;
|
366
|
+
this.fiber = undefined;
|
367
|
+
return interrupt;
|
368
|
+
}
|
369
|
+
}
|
370
|
+
return IO.unit;
|
371
|
+
});
|
297
372
|
}
|
298
373
|
}
|
299
374
|
|
@@ -305,87 +380,26 @@ export function hold<R, E, A>(self: Push<R, E, A>): Push<R, E, A> {
|
|
305
380
|
}
|
306
381
|
|
307
382
|
export class Hold<R, E, A> extends Multicast<R, E, A> {
|
308
|
-
readonly
|
309
|
-
protected pendingEmitters: Array<readonly [Emitter<unknown, E, A>, Array<A>]> = [];
|
310
|
-
protected scheduledFiber: Fiber<any, any> | null = null;
|
383
|
+
readonly current = new AtomicReference(Nothing<A>());
|
311
384
|
|
312
|
-
constructor(
|
385
|
+
constructor(public push: Push<R, E, A>) {
|
313
386
|
super(push);
|
314
387
|
}
|
315
388
|
|
316
|
-
run<R1>(
|
317
|
-
|
318
|
-
return this.scheduleFlush(emitter).flatMap(() => super.run(emitter));
|
319
|
-
}
|
389
|
+
run<R1>(sink: Sink<R1, E, A>): IO<R | R1, never, void> {
|
390
|
+
const current = this.current.get;
|
320
391
|
|
321
|
-
|
322
|
-
|
323
|
-
return emitter.emit(value.value).flatMap(() => super.run(emitter));
|
392
|
+
if (current.isJust()) {
|
393
|
+
return sink.event(current.value) > super.run(sink);
|
324
394
|
}
|
325
395
|
|
326
|
-
return super.run(
|
396
|
+
return super.run(sink);
|
327
397
|
}
|
328
398
|
|
329
|
-
|
399
|
+
event(value: A): IO<never, never, void> {
|
330
400
|
return IO.defer(() => {
|
331
|
-
this.
|
332
|
-
return
|
333
|
-
});
|
334
|
-
}
|
335
|
-
|
336
|
-
failCause(cause: Cause<E>) {
|
337
|
-
return IO.defer(this.flushPending().flatMap(() => super.failCause(cause)));
|
338
|
-
}
|
339
|
-
|
340
|
-
get end() {
|
341
|
-
return IO.defer(this.flushPending().flatMap(() => super.end));
|
342
|
-
}
|
343
|
-
|
344
|
-
protected shouldScheduleFlush() {
|
345
|
-
return this.value.get.isJust() && this.observers.length > 0;
|
346
|
-
}
|
347
|
-
|
348
|
-
protected scheduleFlush<R>(observer: Emitter<R, E, A>) {
|
349
|
-
this.pendingEmitters.push([
|
350
|
-
observer,
|
351
|
-
this.value.get.match(
|
352
|
-
() => [],
|
353
|
-
(a) => [a],
|
354
|
-
),
|
355
|
-
]);
|
356
|
-
|
357
|
-
const interrupt = this.scheduledFiber ? this.scheduledFiber.interruptAsFork(FiberId.none) : IO.unit;
|
358
|
-
this.scheduledFiber = null;
|
359
|
-
|
360
|
-
return (IO.yieldNow > interrupt.flatMap(() => this.flushPending())).forkScoped.tap((fiber) =>
|
361
|
-
IO((this.scheduledFiber = fiber)),
|
362
|
-
);
|
363
|
-
}
|
364
|
-
|
365
|
-
protected flushPending() {
|
366
|
-
if (this.pendingEmitters.length === 0) {
|
367
|
-
return IO.unit;
|
368
|
-
}
|
369
|
-
|
370
|
-
const emitters = this.pendingEmitters;
|
371
|
-
this.pendingEmitters = [];
|
372
|
-
|
373
|
-
return IO.foreachDiscard(emitters, (pendingEmitter) => {
|
374
|
-
return IO.defer(() => {
|
375
|
-
const [emitter, values] = pendingEmitter;
|
376
|
-
const observer = this.observers.find((observer) => observer.emitter === emitter);
|
377
|
-
if (!observer) {
|
378
|
-
return IO.unit;
|
379
|
-
}
|
380
|
-
return IO.foreachDiscard(values, (value) => this.runEvent(value, observer));
|
381
|
-
});
|
382
|
-
});
|
383
|
-
}
|
384
|
-
|
385
|
-
protected addValue(value: A) {
|
386
|
-
this.value.set(Just(value));
|
387
|
-
this.pendingEmitters.forEach(([, values]) => {
|
388
|
-
values.push(value);
|
401
|
+
this.current.set(Just(value));
|
402
|
+
return super.event(value);
|
389
403
|
});
|
390
404
|
}
|
391
405
|
}
|
@@ -406,10 +420,9 @@ export function mapError<E, E1>(f: (e: E) => E1) {
|
|
406
420
|
return <R, A>(self: Push<R, E, A>): Push<R, E1, A> => {
|
407
421
|
return Push((emitter) =>
|
408
422
|
self.run(
|
409
|
-
|
410
|
-
(value) => emitter.
|
411
|
-
(cause) => emitter.
|
412
|
-
emitter.end,
|
423
|
+
Sink(
|
424
|
+
(value) => emitter.event(value),
|
425
|
+
(cause) => emitter.error(cause.map(f)),
|
413
426
|
),
|
414
427
|
),
|
415
428
|
);
|
@@ -423,10 +436,9 @@ export function mapErrorCause<E, E1>(f: (cause: Cause<E>) => Cause<E1>) {
|
|
423
436
|
return <R, A>(self: Push<R, E, A>): Push<R, E1, A> => {
|
424
437
|
return Push((emitter) =>
|
425
438
|
self.run(
|
426
|
-
|
427
|
-
(value) => emitter.
|
428
|
-
(cause) => emitter.
|
429
|
-
emitter.end,
|
439
|
+
Sink(
|
440
|
+
(value) => emitter.event(value),
|
441
|
+
(cause) => emitter.error(f(cause)),
|
430
442
|
),
|
431
443
|
),
|
432
444
|
);
|
@@ -440,14 +452,13 @@ export function mapIO<A, R1, E1, B>(f: (a: A) => IO<R1, E1, B>) {
|
|
440
452
|
return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> =>
|
441
453
|
Push((emitter) =>
|
442
454
|
self.run(
|
443
|
-
|
455
|
+
Sink(
|
444
456
|
(value) =>
|
445
457
|
f(value).matchCauseIO(
|
446
|
-
(cause) => emitter.
|
447
|
-
(b) => emitter.
|
458
|
+
(cause) => emitter.error(cause),
|
459
|
+
(b) => emitter.event(b),
|
448
460
|
),
|
449
|
-
(cause) => emitter.
|
450
|
-
emitter.end,
|
461
|
+
(cause) => emitter.error(cause),
|
451
462
|
),
|
452
463
|
),
|
453
464
|
);
|
@@ -467,29 +478,40 @@ export function merge<R1, E1, B>(that: Push<R1, E1, B>) {
|
|
467
478
|
*/
|
468
479
|
export function mergeAll<A extends ReadonlyArray<Push<any, any, any>>>(
|
469
480
|
streams: [...A],
|
470
|
-
): Push<
|
481
|
+
): Push<Push.EnvironmentOf<A[number]>, Push.ErrorOf<A[number]>, Push.ValueOf<A[number]>>;
|
471
482
|
export function mergeAll<R, E, A>(streams: Iterable<Push<R, E, A>>): Push<R, E, A>;
|
472
483
|
export function mergeAll<R, E, A>(streams: Iterable<Push<R, E, A>>): Push<R, E, A> {
|
473
|
-
return Push((
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
streams.traverseIOConcurrent(
|
478
|
-
(stream) =>
|
479
|
-
stream.run(
|
480
|
-
Emitter(
|
481
|
-
(value) => emitter.emit(value),
|
482
|
-
(cause) => emitter.failCause(cause),
|
483
|
-
latch.countDown,
|
484
|
-
),
|
485
|
-
).forkScoped,
|
486
|
-
),
|
487
|
-
);
|
488
|
-
Δ(latch.await > emitter.end);
|
489
|
-
}),
|
484
|
+
return Push((sink) =>
|
485
|
+
IO.foreachConcurrentDiscard(streams, (stream) =>
|
486
|
+
stream.run(Sink(sink.event, (cause) => (cause.isInterruptedOnly ? IO.unit : sink.error(cause)))),
|
487
|
+
),
|
490
488
|
);
|
491
489
|
}
|
492
490
|
|
491
|
+
/**
|
492
|
+
* @tsplus pipeable fncts.io.Push observe
|
493
|
+
*/
|
494
|
+
export function observe<A, R1, E1>(f: (a: A) => IO<R1, E1, void>, __tsplusTrace?: string) {
|
495
|
+
return <R, E>(self: Push<R, E, A>): IO<R | R1 | Scope, E | E1, void> => {
|
496
|
+
return Do((Δ) => {
|
497
|
+
const future = Δ(Future.make<E | E1, void>());
|
498
|
+
const fiber = Δ(
|
499
|
+
self
|
500
|
+
.run(
|
501
|
+
Sink(
|
502
|
+
(a) => f(a).catchAllCause((cause) => future.failCause(cause)),
|
503
|
+
(cause) => future.failCause(cause),
|
504
|
+
),
|
505
|
+
)
|
506
|
+
.flatMap(() => future.succeed(undefined)).forkScoped,
|
507
|
+
);
|
508
|
+
|
509
|
+
Δ(future.await);
|
510
|
+
Δ(fiber.interruptFork);
|
511
|
+
});
|
512
|
+
};
|
513
|
+
}
|
514
|
+
|
493
515
|
/**
|
494
516
|
* @tsplus static fncts.io.PushOps repeatIOMaybe
|
495
517
|
*/
|
@@ -507,18 +529,7 @@ export function repeatIOMaybe<R, E, A>(io: IO<R, Maybe<E>, A>, __tsplusTrace?: s
|
|
507
529
|
export function runCollect<R, E, A>(self: Push<R, E, A>): IO<R | Scope, E, Conc<A>> {
|
508
530
|
return IO.defer(() => {
|
509
531
|
const out: Array<A> = [];
|
510
|
-
return
|
511
|
-
(future) =>
|
512
|
-
self.run(
|
513
|
-
Emitter(
|
514
|
-
(value) => IO(out.push(value)),
|
515
|
-
(cause) => future.failCause(cause),
|
516
|
-
future.succeed(undefined),
|
517
|
-
),
|
518
|
-
) >
|
519
|
-
future.await >
|
520
|
-
IO(Conc.fromArray(out)),
|
521
|
-
);
|
532
|
+
return self.observe((a) => IO(out.push(a))).as(Conc.fromArray(out));
|
522
533
|
});
|
523
534
|
}
|
524
535
|
|
@@ -526,28 +537,18 @@ export function runCollect<R, E, A>(self: Push<R, E, A>): IO<R | Scope, E, Conc<
|
|
526
537
|
* @tsplus getter fncts.io.Push runDrain
|
527
538
|
*/
|
528
539
|
export function runDrain<R, E, A>(self: Push<R, E, A>): IO<R | Scope, E, void> {
|
529
|
-
return
|
530
|
-
(future) =>
|
531
|
-
self.run(
|
532
|
-
Emitter(
|
533
|
-
() => IO.unit,
|
534
|
-
(cause) => future.failCause(cause),
|
535
|
-
future.succeed(undefined),
|
536
|
-
),
|
537
|
-
) > future.await,
|
538
|
-
);
|
540
|
+
return self.observe(() => IO.unit);
|
539
541
|
}
|
540
542
|
|
541
543
|
/**
|
542
544
|
* @tsplus static fncts.io.PushOps scoped
|
543
545
|
*/
|
544
546
|
export function scoped<R, E, A>(io: Lazy<IO<R, E, A>>, __tsplusTrace?: string): Push<Exclude<R, Scope>, E, A> {
|
545
|
-
return Push(
|
546
|
-
(
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
) > emitter.end,
|
547
|
+
return Push((emitter) =>
|
548
|
+
IO.defer(io).scoped.matchCauseIO(
|
549
|
+
(cause) => emitter.error(cause),
|
550
|
+
(value) => emitter.event(value),
|
551
|
+
),
|
551
552
|
);
|
552
553
|
}
|
553
554
|
|
@@ -559,34 +560,29 @@ export function succeed<A>(value: Lazy<A>): Push<never, never, A> {
|
|
559
560
|
}
|
560
561
|
|
561
562
|
/**
|
562
|
-
* @tsplus pipeable fncts.io.
|
563
|
+
* @tsplus pipeable fncts.io.Push switchMap
|
563
564
|
*/
|
564
565
|
export function switchMap<A, R1, E1, B>(f: (a: A) => Push<R1, E1, B>) {
|
565
566
|
return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
|
566
|
-
return Push(
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
),
|
586
|
-
);
|
587
|
-
Δ(latch.await > emitter.end);
|
588
|
-
}),
|
589
|
-
);
|
567
|
+
return Push((sink) => withSwitch((fork) => self.run(Sink((a) => fork(f(a).run(sink)), sink.error))));
|
568
|
+
};
|
569
|
+
}
|
570
|
+
|
571
|
+
/**
|
572
|
+
* @tsplus pipeable fncts.io.Push switchMapIO
|
573
|
+
*/
|
574
|
+
export function switchMapIO<A, R1, E1, B>(f: (a: A) => IO<R1, E1, B>) {
|
575
|
+
return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
|
576
|
+
return self.switchMap((a) => Push.fromIO(f(a)));
|
577
|
+
};
|
578
|
+
}
|
579
|
+
|
580
|
+
/**
|
581
|
+
* @tsplus pipeable fncts.io.Push tap
|
582
|
+
*/
|
583
|
+
export function tap<A, R1, E1, B>(f: (a: A) => IO<R1, E1, B>) {
|
584
|
+
return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, A> => {
|
585
|
+
return Push((sink) => self.run(Sink((a) => f(a).matchCauseIO(sink.error, () => sink.event(a)), sink.error)));
|
590
586
|
};
|
591
587
|
}
|
592
588
|
|
@@ -600,11 +596,11 @@ export function transform<R1 = never>(f: <R, E, A>(io: IO<R, E, A>) => IO<R | R1
|
|
600
596
|
function unfoldLoop<S, A, R1>(
|
601
597
|
s: S,
|
602
598
|
f: (s: S) => Maybe<readonly [A, S]>,
|
603
|
-
emitter:
|
599
|
+
emitter: Sink<R1, never, A>,
|
604
600
|
): IO<R1, never, void> {
|
605
601
|
return f(s).match(
|
606
|
-
() =>
|
607
|
-
([a, s]) => emitter.
|
602
|
+
() => IO.unit,
|
603
|
+
([a, s]) => emitter.event(a) > unfoldLoop(s, f, emitter),
|
608
604
|
);
|
609
605
|
}
|
610
606
|
|
@@ -618,16 +614,16 @@ export function unfold<S, A>(s: S, f: (s: S) => Maybe<readonly [A, S]>): Push<ne
|
|
618
614
|
function unfoldIOLoop<S, R, E, A, R1>(
|
619
615
|
s: S,
|
620
616
|
f: (s: S) => IO<R, E, Maybe<readonly [A, S]>>,
|
621
|
-
emitter:
|
617
|
+
emitter: Sink<R1, E, A>,
|
622
618
|
): IO<R | R1, never, void> {
|
623
619
|
return f(s)
|
624
620
|
.flatMap((result) =>
|
625
621
|
result.match(
|
626
|
-
() =>
|
627
|
-
([a, s]) => emitter.
|
622
|
+
() => IO.unit,
|
623
|
+
([a, s]) => emitter.event(a) > unfoldIOLoop(s, f, emitter),
|
628
624
|
),
|
629
625
|
)
|
630
|
-
.catchAllCause((cause) => emitter.
|
626
|
+
.catchAllCause((cause) => emitter.error(cause));
|
631
627
|
}
|
632
628
|
|
633
629
|
/**
|
@@ -642,18 +638,21 @@ export function unfoldIO<S, R, E, A>(s: S, f: (s: S) => IO<R, E, Maybe<readonly
|
|
642
638
|
*/
|
643
639
|
export function untilFuture<E1, B>(future: Future<E1, B>) {
|
644
640
|
return <R, E, A>(self: Push<R, E, A>): Push<R, E | E1, A> => {
|
645
|
-
return Push((
|
646
|
-
|
647
|
-
const
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
641
|
+
return Push(<R1>(sink: Sink<R1, E | E1, A>) =>
|
642
|
+
IO.asyncIO<R | R1, never, void>((cb) => {
|
643
|
+
const exit = IO(cb(IO.unit));
|
644
|
+
return Do((Δ) => {
|
645
|
+
const streamFiber = Δ(self.run(sink).fork);
|
646
|
+
const futureFiber = Δ(
|
647
|
+
future.await
|
648
|
+
.matchCauseIO(
|
649
|
+
(cause) => sink.error(cause),
|
650
|
+
() => IO.unit,
|
651
|
+
)
|
652
|
+
.zipRight(exit).fork,
|
653
|
+
);
|
654
|
+
Δ(Fiber.joinAll([streamFiber, futureFiber]));
|
655
|
+
});
|
657
656
|
}),
|
658
657
|
);
|
659
658
|
};
|
@@ -664,19 +663,21 @@ export function untilFuture<E1, B>(future: Future<E1, B>) {
|
|
664
663
|
*/
|
665
664
|
export function untilPush<R1, E1, B>(signal: Push<R1, E1, B>) {
|
666
665
|
return <R, E, A>(self: Push<R, E, A>): Push<R | R1, E | E1, A> => {
|
667
|
-
return Push((
|
668
|
-
|
669
|
-
const
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
(
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
666
|
+
return Push(<R2>(sink: Sink<R2, E | E1, A>) =>
|
667
|
+
IO.asyncIO<R | R1 | R2, never, void>((cb) => {
|
668
|
+
const exit = IO(cb(IO.unit));
|
669
|
+
return Do((Δ) => {
|
670
|
+
const signalFiber = Δ(
|
671
|
+
signal.run(
|
672
|
+
Sink(
|
673
|
+
() => exit,
|
674
|
+
(cause) => sink.error(cause),
|
675
|
+
),
|
676
|
+
).fork,
|
677
|
+
);
|
678
|
+
const streamFiber = Δ(self.run(sink).fork);
|
679
|
+
Δ(Fiber.joinAll([signalFiber, streamFiber]));
|
680
|
+
});
|
680
681
|
}),
|
681
682
|
);
|
682
683
|
};
|