@typed/fp
Version:
Data Structures and Resources for fp-ts
337 lines • 7.27 kB
JavaScript
import { getApplicativeMonoid } from 'fp-ts/Applicative';
import * as Ch from 'fp-ts/Chain';
import * as E from 'fp-ts/Either';
import * as FIO from 'fp-ts/FromIO';
import * as FT from 'fp-ts/FromTask';
import { constant, constVoid, flow, pipe } from 'fp-ts/function';
import { bindTo as bindTo_, tupled as tupled_ } from 'fp-ts/Functor';
import { isNone, none, some } from 'fp-ts/Option';
import * as RA from 'fp-ts/ReadonlyArray';
import { disposeBoth, disposeNone, settable, undisposable } from './Disposable';
/**
* @since 0.9.2
* @category Constructor
*/
export const async = (resume) => ({ _tag: 'async', resume });
/**
* @since 0.9.2
* @category Constructor
*/
export const fromTask = (task) => async((resume) => {
const disposable = settable();
task().then((r) => {
if (!disposable.isDisposed()) {
disposable.addDisposable(resume(r));
}
});
return disposable;
});
/**
* @since 0.9.2
* @category Constructor
*/
export const sync = (resume) => ({ _tag: 'sync', resume });
/**
* @since 0.9.2
* @category Refinement
*/
export const isSync = (resume) => resume._tag === 'sync';
/**
* @since 0.9.2
* @category Refinement
*/
export const isAsync = (resume) => resume._tag === 'async';
/**
* @since 0.9.2
* @category Combinator
*/
export const ap = (fa) => (fab) => {
if (isSync(fa) && isSync(fab)) {
return sync(() => fab.resume()(fa.resume()));
}
// Concurrently
return async((resume) => {
const disposable = settable();
let ab = isSync(fab) ? some(fab.resume()) : none;
let a = isSync(fa) ? some(fa.resume()) : none;
function onReady() {
if (isNone(ab) || isNone(a)) {
return disposeNone();
}
if (!disposable.isDisposed()) {
disposable.addDisposable(resume(ab.value(a.value)));
}
return disposable;
}
if (isAsync(fab)) {
disposable.addDisposable(fab.resume((f) => {
ab = some(f);
return onReady();
}));
}
if (isAsync(fa)) {
disposable.addDisposable(fa.resume((x) => {
a = some(x);
return onReady();
}));
}
return disposable;
});
};
/**
* @since 0.9.2
* @category Deconstructor
*/
export const run = (f) => (resume) => isAsync(resume) ? resume.resume(f) : f(resume.resume());
/**
* @since 0.9.2
* @category Deconstructor
*/
export const start = (f) => run(undisposable(f));
/**
* @since 0.9.2
* @category Deconstructor
*/
export const exec = start(constVoid);
/**
* @since 0.9.2
* @category Deconstructor
*/
export const toTask = (resume) => {
const task = () => {
const d = settable();
const p = new Promise((resolve) => d.addDisposable(pipe(resume, start(resolve))));
p.dispose = () => d.dispose();
return p;
};
return task;
};
/**
* @since 0.9.2
* @category Combinator
*/
export const chain = (f) => (resume) => isSync(resume) ? f(resume.resume()) : async((r) => resume.resume(flow(f, run(r))));
/**
* @since 0.9.2
* @category Constructor
*/
export const of = flow(constant, sync);
/**
* @since 0.9.2
* @category Combinator
*/
export const chainRec = (f) => (value) => {
let resume = f(value);
while (isSync(resume)) {
const either = resume.resume();
if (E.isRight(either)) {
return of(either.right);
}
resume = f(either.left);
}
// Recursion is okay because Resume SHOULD be asynchronous
return pipe(resume, chain(E.match(chainRec(f), of)));
};
/**
* @since 0.9.2
* @category Combinator
*/
export const race = (ra) => (rb) => {
if (isSync(rb)) {
return rb;
}
if (isSync(ra)) {
return ra;
}
return async((resume) => {
const aDisposableLazy = settable();
const bDisposable = pipe(rb, run((b) => {
aDisposableLazy.dispose();
return resume(b);
}));
const aDisposable = pipe(ra, run((a) => {
bDisposable.dispose();
return resume(a);
}));
aDisposableLazy.addDisposable(aDisposable);
return disposeBoth(bDisposable, aDisposable);
});
};
/**
* @since 0.9.2
* @category URI
*/
export const URI = '@typed/fp/Resume';
/**
* @since 0.9.2
* @category Instance
*/
export const Pointed = {
of,
};
/**
* @since 0.9.2
* @category Instance
*/
export const Functor = {
URI,
map: (f) => (fa) => pipe(fa, chain(flow(f, of))),
};
/**
* @since 0.9.2
* @category Combinator
*/
export const map = Functor.map;
/**
* @since 0.9.2
* @category Instance
*/
export const Apply = {
...Functor,
ap,
};
/**
* @since 0.9.2
* @category Instance
*/
export const Applicative = {
...Apply,
...Pointed,
};
/**
* @since 0.9.2
* @category Instance
*/
export const Chain = {
...Functor,
chain,
};
/**
* @since 0.9.2
* @category Combinator
*/
export const chainFirst = Ch.chainFirst(Chain);
/**
* @since 0.9.2
* @category Instance
*/
export const Monad = {
...Chain,
...Pointed,
};
/**
* @since 0.9.2
* @category Instance
*/
export const ChainRec = {
URI,
chainRec,
};
/**
* @since 0.9.2
* @category Instance
*/
export const MonadRec = {
...Monad,
chainRec,
};
/**
* @since 0.9.2
* @category Instance
*/
export const Alt = {
...Functor,
alt: (snd) => (fst) => pipe(fst, race(snd())),
};
/**
* @since 0.9.2
* @category Instance
*/
export const FromIO = {
URI,
fromIO: sync,
};
/**
* @since 0.9.2
* @category Constructor
*/
export const fromIO = FromIO.fromIO;
/**
* @since 0.9.2
* @category Instance
*/
export const FromTask = {
...FromIO,
fromTask,
};
/**
* @since 0.9.2
* @category Constructor
*/
export const Do = sync(() => Object.create(null));
/**
* @since 0.9.2
* @category Combinator
*/
export const bindTo = bindTo_(Functor);
/**
* @since 0.9.2
* @category Combinator
*/
export const bind = Ch.bind(Monad);
/**
* @since 0.9.2
* @category Combinator
*/
export const tupled = tupled_(Functor);
/**
* @since 0.9.2
* @category Combinator
*/
export const traverseReadonlyArray = RA.traverse(Applicative);
/**
* @since 0.9.2
* @category Combinator
*/
export const traverseReadonlyArrayWithIndex = RA.traverseWithIndex(Applicative);
/**
* @since 0.9.2
* @category Combinator
*/
export const zip = traverseReadonlyArray((x) => x);
/**
* @since 0.9.2
* @category Combinator
*/
export const chainFirstTaskK = FT.chainFirstTaskK(FromTask, Chain);
/**
* @since 0.9.2
* @category Combinator
*/
export const chainTaskK = FT.chainTaskK(FromTask, Chain);
/**
* @since 0.9.2
* @category Constructor
*/
export const fromTaskK = FT.fromTaskK(FromTask);
/**
* @since 0.9.2
* @category Combinator
*/
export const chainFirstIOK = FIO.chainFirstIOK(FromIO, Chain);
/**
* @since 0.9.2
* @category Combinator
*/
export const chainIOK = FIO.chainIOK(FromIO, Chain);
/**
* @since 0.9.2
* @category Constructor
*/
export const fromIOK = FIO.fromIOK(FromIO);
/**
* @since 0.9.2
* @category Typeclass Constructor
*/
export const getMonoid = getApplicativeMonoid(Applicative);
//# sourceMappingURL=Resume.js.map