/** * Represents an empty list */ export type Nil = {readonly _tag: 'Nil'} /** * Represents a non-empty list node * @typeParam A - The type of elements in the list */ export type Cons = { readonly _tag: 'Cons', readonly head: A, readonly tail: List, } /** * A recursive list type that is either Nil (empty) or Cons (non-empty) * @typeParam A - The type of elements in the list */ export type List = Nil | Cons /** * The singleton instance of an empty list */ export const nil: Nil = {_tag: 'Nil'} /** * Constructs a new list node * @typeParam A - The type of elements in the list * @param head - The first element of the list * @param tail - The rest of the list * @returns A new Cons node */ export const cons = (head: A, tail: List): List => ({ _tag: 'Cons', head, tail, }) /** * Maps a function over all elements of a list * @typeParam A - The input element type * @typeParam B - The output element type * @param f - The mapping function * @returns A function that takes a list and returns a new list */ type ListMap = (f: (a: A) => B) => (fa: List) => List export const listMap: ListMap = (f) => (fa) => fa._tag === 'Cons' ? cons(f(fa.head), listMap(f)(fa.tail)) : nil /** * Reduces a list to a single value * @typeParam A - The element type * @typeParam B - The accumulator type * @param f - The reducer function * @param initial - The initial accumulator value * @returns A function that takes a list and returns the reduced value */ type ListReduce = (f: (b: B, a: A) => B, initial: B) => (fa: List) => B export const listReduce: ListReduce = (f: (b: B, a: A) => B, initial: B) => (fa: List) => { const reduceHelper = (list: List, acc: B): B => { return list._tag === 'Cons' ? reduceHelper(list.tail, f(acc, list.head)) : acc } return reduceHelper(fa, initial) } /** * Creates a list from an array * @typeParam A - The element type * @param arr - The source array * @returns A list containing the same elements */ type FromArray = (arr: Array) => List export const fromArray: FromArray = (arr: Array) => arr.reduceRight( (acc: List, val: A) => cons(val, acc), nil as List, ) /** * Converts a list to an array * @typeParam A - The element type * @param fa - The list to convert * @returns An array containing the same elements */ type ToArray = (fa: List) => Array export const toArray: ToArray = (fa: List) => listReduce>( (acc, val) => [...acc, val], [] as Array, )(fa)