95 lines
2.5 KiB
TypeScript
95 lines
2.5 KiB
TypeScript
/**
|
|
* 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<A> = {
|
|
readonly _tag: 'Cons',
|
|
readonly head: A,
|
|
readonly tail: List<A>,
|
|
}
|
|
|
|
/**
|
|
* 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<A> = Nil | Cons<A>
|
|
|
|
/**
|
|
* 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 = <A>(head: A, tail: List<A>): List<A> => ({
|
|
_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 = <A, B>(f: (a: A) => B) => (fa: List<A>) => List<B>
|
|
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 = <A, B>(f: (b: B, a: A) => B, initial: B) => (fa: List<A>) => B
|
|
export const listReduce: ListReduce =
|
|
<A, B>(f: (b: B, a: A) => B, initial: B) => (fa: List<A>) => {
|
|
const reduceHelper = (list: List<A>, 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 = <A>(arr: Array<A>) => List<A>
|
|
export const fromArray: FromArray = <A>(arr: Array<A>) =>
|
|
arr.reduceRight(
|
|
(acc: List<A>, val: A) => cons(val, acc),
|
|
nil as List<A>,
|
|
)
|
|
|
|
/**
|
|
* 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 = <A>(fa: List<A>) => Array<A>
|
|
export const toArray: ToArray = <A>(fa: List<A>) =>
|
|
listReduce<A, Array<A>>(
|
|
(acc, val) => [...acc, val],
|
|
[] as Array<A>,
|
|
)(fa)
|