import { bench, describe } from 'vitest'; import { STANDARD, EXTENDED } from '../helpers/bench-options.js'; import { SIZES, errorIndices } from '../helpers/data-generators.js'; import { okSome, okNone, errNone, Query, E, O, pipe, } from '../helpers/imports.js'; import * as RA from 'fp-ts/ReadonlyArray'; // --------------------------------------------------------------------------- // Query.all — all OkSome // --------------------------------------------------------------------------- for (const size of SIZES) { const opts = size >= 10_000 ? EXTENDED : STANDARD; const nmAll = Array.from({ length: size }, (_, i) => okSome(i)); const fpAll = Array.from({ length: size }, (_, i) => E.right(O.some(i)) as E.Either>, ); describe(`Query.all — ${size} items, all OkSome`, () => { bench('native-monad', () => { Query.all(nmAll); }, opts); bench('fp-ts (nested, manual)', () => { const values: number[] = []; for (const item of fpAll) { if (E.isLeft(item)) return item; if (O.isNone(item.right)) continue; values.push(item.right.value); } return E.right(O.some(values)); }, opts); }); } // --------------------------------------------------------------------------- // Query.all — mixed (OkSome + OkNone + ErrNone) // --------------------------------------------------------------------------- for (const size of SIZES) { const opts = size >= 10_000 ? EXTENDED : STANDARD; const errIdx = errorIndices(size, 0.1); const noneIdx = errorIndices(size, 0.15); const nmMixed = Array.from({ length: size }, (_, i) => { if (errIdx.has(i)) return errNone('fail'); if (noneIdx.has(i)) return okNone(); return okSome(i); }); const fpMixed = Array.from({ length: size }, (_, i) => { if (errIdx.has(i)) return E.left('fail') as E.Either>; if (noneIdx.has(i)) return E.right(O.none) as E.Either>; return E.right(O.some(i)) as E.Either>; }); describe(`Query.all — ${size} items, mixed (short-circuit)`, () => { bench('native-monad', () => { Query.all(nmMixed); }, opts); bench('fp-ts (nested, manual)', () => { const values: number[] = []; for (const item of fpMixed) { if (E.isLeft(item)) return item; if (O.isNone(item.right)) continue; values.push(item.right.value); } return E.right(O.some(values)); }, opts); }); } // --------------------------------------------------------------------------- // Query.partition // --------------------------------------------------------------------------- for (const size of SIZES) { const opts = size >= 10_000 ? EXTENDED : STANDARD; const errIdx = errorIndices(size, 0.1); const noneIdx = errorIndices(size, 0.15); const nmMixed = Array.from({ length: size }, (_, i) => { if (errIdx.has(i)) return errNone('fail'); if (noneIdx.has(i)) return okNone(); return okSome(i); }); const fpMixed = Array.from({ length: size }, (_, i) => { if (errIdx.has(i)) return E.left('fail') as E.Either>; if (noneIdx.has(i)) return E.right(O.none) as E.Either>; return E.right(O.some(i)) as E.Either>; }); describe(`Query.partition — ${size} items`, () => { bench('native-monad', () => { Query.partition(nmMixed); }, opts); bench('fp-ts (nested, manual)', () => { const values: number[] = []; const errors: string[] = []; let noneCount = 0; for (const item of fpMixed) { if (E.isLeft(item)) { errors.push(item.left); continue; } if (O.isNone(item.right)) { noneCount++; continue; } values.push(item.right.value); } return { values, noneCount, errors }; }, opts); }); } // --------------------------------------------------------------------------- // Query.compact // --------------------------------------------------------------------------- for (const size of SIZES) { const opts = size >= 10_000 ? EXTENDED : STANDARD; const errIdx = errorIndices(size, 0.1); const noneIdx = errorIndices(size, 0.15); const nmMixed = Array.from({ length: size }, (_, i) => { if (errIdx.has(i)) return errNone('fail'); if (noneIdx.has(i)) return okNone(); return okSome(i); }); const fpMixed = Array.from({ length: size }, (_, i) => { if (errIdx.has(i)) return E.left('fail') as E.Either>; if (noneIdx.has(i)) return E.right(O.none) as E.Either>; return E.right(O.some(i)) as E.Either>; }); describe(`Query.compact — ${size} items`, () => { bench('native-monad', () => { Query.compact(nmMixed); }, opts); bench('fp-ts (nested, manual)', () => { const values: number[] = []; for (const item of fpMixed) { if (E.isRight(item) && O.isSome(item.right)) values.push(item.right.value); } return values; }, opts); }); }