A (Array)
Every function works both ways: A.fn(arr, ...) (data-first) and pipe(arr, A.fn(...)) (data-last).
Accessors
Section titled “Accessors”head<A>(arr: A[]): A | undefinedlast<A>(arr: A[]): A | undefinedfirst<A>(arr: A[]): A | undefined // alias for headtail<A>(arr: A[]): A[] // all except firstinit<A>(arr: A[]): A[] // all except lastlength<A>(arr: A[]): numberisEmpty<A>(arr: A[]): booleanTransforms
Section titled “Transforms”map<A, B>(arr: A[], f: (a: A) => B): B[]mapWithIndex<A, B>(arr: A[], f: (a: A, i: number) => B): B[]filter<A>(arr: A[], pred: (a: A) => boolean): A[]filterWithIndex<A>(arr: A[], pred: (a: A, i: number) => boolean): A[]flatMap<A, B>(arr: A[], f: (a: A) => B[]): B[]reduce<A, B>(arr: A[], f: (acc: B, a: A) => B, init: B): BreduceRight<A, B>(arr: A[], f: (acc: B, a: A) => B, init: B): Bscan<A, B>(arr: A[], f: (acc: B, a: A) => B, init: B): B[]forEach<A>(arr: A[], f: (a: A) => void): voidforEachWithIndex<A>(arr: A[], f: (a: A, i: number) => void): voidAll of these fuse in pipe.
Ordering
Section titled “Ordering”sort(arr: number[]): number[]sortBy<A>(arr: A[], cmp: (a: A, b: A) => number): A[]reverse<A>(arr: A[]): A[]Not fuseable. They need the whole array.
Slicing
Section titled “Slicing”take<A>(arr: A[], n: number): A[]drop<A>(arr: A[], n: number): A[]takeWhile<A>(arr: A[], pred: (a: A) => boolean): A[]dropWhile<A>(arr: A[], pred: (a: A) => boolean): A[]chunk<A>(arr: A[], n: number): A[][]slidingWindow<A>(arr: A[], n: number): A[][]aperture<A>(arr: A[], n: number): A[][]take bails out early in fused pipelines.
Search
Section titled “Search”find<A>(arr: A[], pred: (a: A) => boolean): A | undefinedfindIndex<A>(arr: A[], pred: (a: A) => boolean): number | undefinedevery<A>(arr: A[], pred: (a: A) => boolean): booleansome<A>(arr: A[], pred: (a: A) => boolean): booleanincludes<A>(arr: A[], value: A): booleanfind, every, some fuse and bail out early.
Deduplication
Section titled “Deduplication”uniq<A>(arr: A[]): A[]uniqBy<A, B>(arr: A[], f: (a: A) => B): A[]Set operations
Section titled “Set operations”intersection<A>(a: A[], b: A[]): A[]union<A>(a: A[], b: A[]): A[]difference<A>(a: A[], b: A[]): A[]symmetricDifference<A>(a: A[], b: A[]): A[]Combinators
Section titled “Combinators”zip<A, B>(a: A[], b: B[]): [A, B][]zipWith<A, B, C>(a: A[], b: B[], f: (a: A, b: B) => C): C[]xprod<A, B>(a: A[], b: B[]): [A, B][]groupBy<A>(arr: A[], f: (a: A) => string): Dict<A[]>partition<A>(arr: A[], pred: (a: A) => boolean): [A[], A[]]intersperse<A>(arr: A[], sep: A): A[]flatten<A>(arr: A[][]): A[]transpose<A>(arr: A[][]): A[][]Mutation (immutable)
Section titled “Mutation (immutable)”adjust<A>(arr: A[], index: number, f: (a: A) => A): A[]update<A>(arr: A[], index: number, value: A): A[]insert<A>(arr: A[], index: number, value: A): A[]remove<A>(arr: A[], index: number, count: number): A[]All return new arrays.
Constructors
Section titled “Constructors”range(start: number, end: number): number[]repeat<A>(value: A, n: number): A[]times<A>(f: (i: number) => A, n: number): A[]unfold<A, B>(f: (seed: B) => [A, B] | undefined, seed: B): A[]Examples
Section titled “Examples”import { pipe, A } from '@stopcock/fp'
type Product = { name: string; price: number; category: string; inStock: boolean }
// fused: filter → map → take runs in one loopconst deals = pipe( products, A.filter((p: Product) => p.inStock && p.price < 50), A.map(p => ({ name: p.name, price: p.price })), A.take(10),)
// group + countconst byCategory = A.groupBy(products, p => p.category)// { electronics: [...], clothing: [...] }
// rolling totalA.scan([100, 200, 150, 300], (acc, x) => acc + x, 0)// [100, 300, 450, 750]
// remove duplicates by keyconst uniqueCustomers = pipe( orders, A.uniqBy((o: { customerId: string }) => o.customerId),)
// set operationsconst newUsers = A.difference(allUsers, existingUsers)const commonTags = A.intersection(tagsA, tagsB)
// batch processingconst batches = A.chunk(records, 100)