spica
Version:
Supervisor, Coroutine, Channel, select, AtomicPromise, Cancellation, Cache, List, Queue, Stack, and some utils.
54 lines (50 loc) • 1.55 kB
text/typescript
import { Tail, Reverse } from '../type';
import { unshift } from '../array';
export type HList<as extends [] | [unknown, ...unknown[]]> =
as extends readonly [] ? HNil :
HCons<as>;
export function HList<as extends [] | [unknown, ...unknown[]]>(...as: as): HList<as>;
export function HList<as extends unknown[]>(...as: as): HList<any> {
return as.reduceRight<HList<any>>((node, a) => node.add(a), HNil as any);
}
type HNil = typeof HNil;
const HNil = new class HNil {
public add<a>(a: a): HCons<[a]> {
return new HCons(a, this);
}
public reverse(): [] {
return [];
}
public tuple(): [] {
return [];
}
}();
class HCons<as extends unknown[]> {
constructor(
public readonly head: as[0],
public readonly tail: as extends readonly [unknown, unknown, ...unknown[]] ? HCons<Tail<as>> : HNil,
) {
}
public add<a>(a: a): HCons<[a, ...as]> {
// @ts-ignore
return new HCons(a, this);
}
public modify<a>(f: (a: as[0]) => a): HCons<[a, ...Tail<as>]> {
// @ts-ignore
return this.tail.add(f(this.head));
}
public fold<a>(this: HCons<[unknown, unknown, ...unknown[]]>, f: (l: as[0], r: as[1]) => a): HCons<[a, ...Tail<Tail<as>>]> {
// @ts-ignore
return this.tail.modify(r => f(this.head, r));
}
public unfold<a>(f: (a: as[0]) => a): HCons<[a, ...as]> {
// @ts-ignore
return this.add(f(this.head));
}
public reverse(): Reverse<as> {
return this.tuple().reverse() as Reverse<as>;
}
public tuple(): as {
return unshift([this.head], this.tail.tuple()) as as;
}
}