spica
Version:
Supervisor, Coroutine, Channel, select, AtomicPromise, Cancellation, Cache, List, Queue, Stack, and some utils.
150 lines (146 loc) • 8.99 kB
text/typescript
import { MonadPlus } from '../monadplus';
export class Sequence<a, z> extends MonadPlus<a> implements Iterable<a> {
constructor(
protected readonly cons: (z: z, cons: (a?: a, z?: z) => Sequence.Data<a, z>) => Sequence.Data<a, z>
) {
super(throwCallError);
}
public [Symbol.iterator](): Iterator<a, undefined, undefined> {
let iter = () => this.iterate();
return {
next() {
const thunk = iter();
iter = Sequence.Thunk.iterator(thunk);
return {
done: !Sequence.isIterable(thunk),
value: Sequence.Thunk.value(thunk)
} as IteratorResult<a, undefined>;
}
};
}
}
export namespace Sequence {
export declare function resume<a>(iterator: Sequence.Iterator<a>): Sequence<a, Sequence.Iterator<a>>;
export declare function from<a>(as: Iterable<a>): Sequence<a, [number, Map<number, Sequence.Thunk<a>>]>;
export declare function cycle<a>(as: Iterable<a>): Sequence<a, [number, Map<number, Sequence.Thunk<a>>]>;
export declare function random(): Sequence<number, [number, Map<number, Sequence.Thunk<number>>]>;
export declare function random<a>(gen: () => a): Sequence<a, [number, Map<number, Sequence.Thunk<a>>]>;
export declare function random<a>(as: a[]): Sequence<a, Sequence.Iterator<number>>;
export declare function concat<a>(as: Sequence<Sequence<a, unknown>, unknown>): Sequence<a, [Sequence.Iterator<Sequence<a, unknown>>, Sequence.Iterator<a>]>;
export declare function zip<a, b>(a: Sequence<a, unknown>, b: Sequence<b, unknown>): Sequence<[a, b], [Sequence.Iterator<a>, Sequence.Iterator<b>]>;
export declare function difference<a>(a: Sequence<a, unknown>, b: Sequence<a, unknown>, cmp: (l: a, r: a) => number): Sequence<a, [Sequence.Iterator<a>, Sequence.Iterator<a>]>;
export declare function union<a>(a: Sequence<a, unknown>, b: Sequence<a, unknown>, cmp: (l: a, r: a) => number): Sequence<a, [Sequence.Iterator<a>, Sequence.Iterator<a>]>;
export declare function intersect<a>(a: Sequence<a, unknown>, b: Sequence<a, unknown>, cmp: (l: a, r: a) => number): Sequence<a, [Sequence.Iterator<a>, Sequence.Iterator<a>]>;
export declare function fmap<a, b>(f: (a: a) => b, m: Sequence<a, unknown>): Sequence<b, Sequence.Iterator<a>>;
export declare function pure<a>(a: a): Sequence<a, number>;
export declare function ap<a, b>(mf: Sequence<(a: a) => b, unknown>, ma: Sequence<a, unknown>): Sequence<b, [Sequence.Iterator<Sequence<b, unknown>>, Sequence.Iterator<b>]>;
export declare function ap<a, b>(mf: Sequence<(a: a) => b, unknown>): (ma: Sequence<a, unknown>) => Sequence<b, [Sequence.Iterator<Sequence<b, unknown>>, Sequence.Iterator<b>]>;
export declare const Return: typeof pure;
export declare function bind<a, b>(f: (a: a) => Sequence<b, unknown>, m: Sequence<a, unknown>): Sequence<b, Sequence.Iterator<a>>;
export declare function sequence<b>(ms: Sequence<b, unknown>[]): Sequence<Sequence<b, [Sequence.Iterator<b>, Sequence.Iterator<b>]>, Sequence.Iterator<Sequence<b, [Sequence.Iterator<b>, Sequence.Iterator<b>]>>>;
export declare const mempty: Sequence<never, never>;
export declare function mappend<a>(l: Sequence<a, unknown>, r: Sequence<a, unknown>): Sequence<a, [Sequence.Iterator<a>, Sequence.Iterator<a>]>;
export declare function mconcat<a>(as: Iterable<Sequence<a, unknown>>): Sequence<a, [Sequence.Iterator<a>, Sequence.Iterator<a>]>;
export declare const mzero: Sequence<never, never>;
export declare function mplus<a>(l: Sequence<a, unknown>, r: Sequence<a, unknown>): Sequence<a, [Sequence.Iterator<a>, Sequence.Iterator<a>]>;
}
export interface Sequence<a, z> {
extract(): a[];
[Symbol.iterator](): Iterator<a>;
iterate(): Sequence.Thunk<a>;
fmap<b>(f: (a: a) => b): Sequence<b, Sequence.Iterator<a>>;
ap<a, z>(this: Sequence<(a: a) => z, unknown>, a: Sequence<a, unknown>): Sequence<z, [Sequence.Iterator<Sequence<z, unknown>>, Sequence.Iterator<z>]>;
ap<a, b, z>(this: Sequence<(a: a, b: b) => z, unknown>, a: Sequence<a, unknown>): Sequence<(b: b) => z, [Sequence.Iterator<Sequence<z, unknown>>, Sequence.Iterator<z>]>;
ap<a, b, c, z>(this: Sequence<(a: a, b: b, c: c) => z, unknown>, a: Sequence<a, unknown>): Sequence<(b: b, c: c) => z, [Sequence.Iterator<Sequence<z, unknown>>, Sequence.Iterator<z>]>;
ap<a, b, c, d, z>(this: Sequence<(a: a, b: b, c: c, d: d) => z, unknown>, a: Sequence<a, unknown>): Sequence<(b: b, c: c, d: d) => z, [Sequence.Iterator<Sequence<z, unknown>>, Sequence.Iterator<z>]>;
ap<a, b, c, d, e, z>(this: Sequence<(a: a, b: b, c: c, d: d, e: e) => z, unknown>, a: Sequence<a, unknown>): Sequence<(b: b, c: c, d: d, e: e) => z, [Sequence.Iterator<Sequence<z, unknown>>, Sequence.Iterator<z>]>;
bind<b>(f: (a: a) => Sequence<b, unknown>): Sequence<b, [Sequence.Iterator<Sequence<b, unknown>>, Sequence.Iterator<b>]>;
join<b>(this: Sequence<Sequence<b, unknown>, unknown>): Sequence<b, [Sequence.Iterator<Sequence<b, unknown>>, Sequence.Iterator<b>]>;
mapM<b>(f: (a: a) => Sequence<b, unknown>): Sequence<b[], [Sequence.Iterator<Sequence<b[], unknown>>, Sequence.Iterator<b[]>]>;
filterM(f: (a: a) => Sequence<boolean, unknown>): Sequence<a[], [Sequence.Iterator<Sequence<a[], unknown>>, Sequence.Iterator<a[]>]>;
map<b>(f: (a: a, i: number) => b): Sequence<b, Sequence.Iterator<a>>;
filter(f: (a: a, i: number) => boolean): Sequence<a, Sequence.Iterator<a>>;
scanl<b>(f: (b: b, a: a) => b, z: b): Sequence<b, [b, Sequence.Iterator<a>, number]>;
foldr<b>(f: (a: a, b: Sequence<b, unknown>) => Sequence<b, unknown>, z: Sequence<b, unknown>): Sequence<b, [Sequence.Iterator<Sequence<b, unknown>>, Sequence.Iterator<b>]>;
group(f: (x: a, y: a) => boolean): Sequence<a[], [Sequence.Iterator<a>, a[]]>;
inits(): Sequence<a[], [Sequence.Iterator<a[]>, Sequence.Iterator<a[]>]>
tails(): Sequence<a[], [Sequence.Iterator<a[]>, Sequence.Iterator<a[]>]>
segs(): Sequence<a[], [Sequence.Iterator<a[]>, Sequence.Iterator<a[]>]>;
subsequences(): Sequence<a[], [Sequence.Iterator<a[]>, Sequence.Iterator<a[]>]>;
permutations(): Sequence<a[], [Sequence.Iterator<Sequence<a[], unknown>>, Sequence.Iterator<a[]>]>;
take(n: number): Sequence<a, Sequence.Iterator<a>>;
drop(n: number): Sequence<a, Sequence.Iterator<a>>;
takeWhile(f: (a: a) => boolean): Sequence<a, Sequence.Iterator<a>>;
dropWhile(f: (a: a) => boolean): Sequence<a, Sequence.Iterator<a>>;
takeUntil(f: (a: a) => boolean): Sequence<a, Sequence.Iterator<a>>;
dropUntil(f: (a: a) => boolean): Sequence<a, Sequence.Iterator<a>>;
sort(cmp?: (a: a, b: a) => number): Sequence<a, [number, Map<number, Sequence.Thunk<a>>]>;
unique(): Sequence<a, Sequence.Iterator<a>>;
memoize(): Sequence<a, [number, Map<number, Sequence.Thunk<a>>]>;
reduce(): Sequence<a, [number, Map<number, Sequence.Thunk<a>>]>;
}
export namespace Sequence {
export type Data<a, z> = [] | [a] | [a, z];
export namespace Data {
export function cons<a, z>(): [];
export function cons<a, z>(a: a): [a];
export function cons<a, z>(a: a, z: z): [a, z];
export function cons<a, z>(a?: a, z?: z): Data<a, z> {
switch (arguments.length) {
case 0:
return [];
case 1:
return [a!];
case 2:
return [a!, z!];
default:
throw Sequence.Exception.invalidConsError(arguments);
}
}
}
export type Thunk<a> = [a, Iterator<a>, number];
export namespace Thunk {
export function value<a>(thunk: Thunk<a>): a {
return thunk[0];
}
export function iterator<a>(thunk: Thunk<a>): Iterator<a> {
return thunk[1];
}
export function index<a>(thunk: Thunk<a>): number {
return thunk[2];
}
}
export type Iterator<a> = () => Thunk<a>;
export namespace Iterator {
export const done: Sequence.Iterator<never> = () => <Sequence.Thunk<never>>[undefined, done, -1];
export function when<a, b>(
thunk: Thunk<a>,
caseDone: (thunk: Thunk<a>) => b,
caseIterable: (thunk: Thunk<a>, recur: () => b) => b
): b {
return Sequence.isIterable(thunk)
? caseIterable(thunk, () => when(Thunk.iterator(thunk)(), caseDone, caseIterable))
: caseDone(thunk);
}
}
export function isIterable(thunk: Thunk<unknown>): boolean {
return Thunk.iterator(thunk) !== Iterator.done;
}
export namespace Exception {
export function invalidConsError(args: IArguments): TypeError {
console.error(args, args.length, args[0], args[1]);
return new TypeError(`Spica: Sequence: Invalid parameters of cons`);
}
export function invalidDataError(data: unknown[]): TypeError {
console.error(data);
return new TypeError(`Spica: Sequence: Invalid data`);
}
export function invalidThunkError(thunk: Sequence.Thunk<unknown>): TypeError {
console.error(thunk);
return new TypeError(`Spica: Sequence: Invalid thunk`);
}
}
}
function throwCallError(): never {
throw new Error(`Spica: Sequence: Invalid thunk call`);
}