UNPKG

spica

Version:

Supervisor, Coroutine, Channel, select, AtomicPromise, Cancellation, Cache, List, Queue, Stack, and some utils.

54 lines (50 loc) 1.55 kB
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; } }