summaryrefslogtreecommitdiff
path: root/u/types/collections/cons.ts
blob: 05dbe7cc70b13f784d73f4293bbfb6b6b7a59846 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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());
    }
}