forked from baetheus/fun
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathasync.ts
More file actions
80 lines (66 loc) · 1.85 KB
/
async.ts
File metadata and controls
80 lines (66 loc) · 1.85 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
import type { Kind, Out } from "./kind.ts";
import type { Monad } from "./monad.ts";
import type { Sync } from "./sync.ts";
import { resolve, wait } from "./promise.ts";
import { handleThrow } from "./fn.ts";
export type Async<A> = Sync<Promise<A>>;
export interface KindAsync extends Kind {
readonly kind: Async<Out<this, 0>>;
}
export function of<A>(a: A): Async<A> {
return () => resolve(a);
}
export function delay(ms: number): <A>(ma: Async<A>) => Async<A> {
return (ta) => () => wait(ms).then(ta);
}
export function fromSync<A>(fa: Sync<A>): Async<A> {
return () => resolve(fa());
}
export function tryCatch<AS extends unknown[], A>(
fasr: (...as: AS) => A | PromiseLike<A>,
onThrow: (e: unknown, as: AS) => A,
): (...as: AS) => Async<A> {
return (...as) => {
const _onThrow = (e: unknown) => onThrow(e, as);
return handleThrow(
() => fasr(...as),
(a) => resolve(a).catch(_onThrow),
(e) => resolve(_onThrow(e)),
);
};
}
export function map<A, I>(fai: (a: A) => I): (ta: Async<A>) => Async<I> {
return (ta) => () => ta().then(fai);
}
export function apParallel<A>(
ua: Async<A>,
): <I>(ufai: Async<(a: A) => I>) => Async<I> {
return (ufai) => () => Promise.all([ufai(), ua()]).then(([fai, a]) => fai(a));
}
export function apSequential<A>(
ua: Async<A>,
): <I>(ufai: Async<(a: A) => I>) => Async<I> {
return (ufai) => async () => (await ufai())(await ua());
}
export function join<A>(tta: Async<Async<A>>): Async<A> {
return () => tta().then((ta) => ta());
}
export function chain<A, I>(
fati: (a: A) => Async<I>,
): (ta: Async<A>) => Async<I> {
return (ta) => () => ta().then((a) => fati(a)());
}
export const MonadAsyncParallel: Monad<KindAsync> = {
of,
ap: apParallel,
map,
join,
chain,
};
export const MonadAsyncSequential: Monad<KindAsync> = {
of,
ap: apSequential,
map,
join,
chain,
};