diff options
Diffstat (limited to 'u/types/collections/cons.ts')
-rw-r--r-- | u/types/collections/cons.ts | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/u/types/collections/cons.ts b/u/types/collections/cons.ts new file mode 100644 index 0000000..05dbe7c --- /dev/null +++ b/u/types/collections/cons.ts @@ -0,0 +1,40 @@ +import { IOptional, Mapper, Optional } from '@emprespresso/pengueno'; + +export interface ICons<T> extends Iterable<T> { + readonly value: T; + readonly next: IOptional<ICons<T>>; + + readonly replace: Mapper<T, ICons<T>>; + readonly before: Mapper<IOptional<ICons<T>>, ICons<T>>; +} + +export class Cons<T> implements ICons<T> { + constructor( + public readonly value: T, + public readonly next: IOptional<ICons<T>> = Optional.none(), + ) {} + + public before(head: IOptional<ICons<T>>): ICons<T> { + return new Cons<T>(this.value, head); + } + + public replace(_value: T): ICons<T> { + return new Cons<T>(_value, this.next); + } + + *[Symbol.iterator]() { + for (let cur = Optional.some<ICons<T>>(this); cur.present(); cur = cur.flatMap((cur) => cur.next)) { + yield cur.get().value; + } + } + + static addOnto<T>(items: Iterable<T>, tail: IOptional<ICons<T>>): IOptional<ICons<T>> { + return Array.from(items) + .reverse() + .reduce((cons, value) => Optional.from<ICons<T>>(new Cons<T>(value, cons)), tail); + } + + static from<T>(items: Iterable<T>): IOptional<ICons<T>> { + return Cons.addOnto(items, Optional.none()); + } +} |