import { bench, describe } from 'vitest'; import { STANDARD, EXTENDED } from '../helpers/bench-options.js'; import { SIZES, errorIndices } from '../helpers/data-generators.js'; import { some, none, Option, TsSome, TsNone, TsOption, OxSome, OxNone, O, pipe, TmMaybe, } from '../helpers/imports.js'; import * as RA from 'fp-ts/ReadonlyArray'; // --------------------------------------------------------------------------- // Option.all — all Some // --------------------------------------------------------------------------- for (const size of SIZES) { const opts = size >= 10_000 ? EXTENDED : STANDARD; const nmAll = Array.from({ length: size }, (_, i) => some(i)); const tsAll = Array.from({ length: size }, (_, i) => TsSome(i)); const fpAll = Array.from({ length: size }, (_, i) => O.some(i)); const tmAll = Array.from({ length: size }, (_, i) => TmMaybe.just(i)); describe(`Option.all — ${size} items, all Some`, () => { bench('native-monad', () => { Option.all(nmAll); }, opts); bench('ts-results-es', () => { TsOption.all(...tsAll); }, opts); bench('fp-ts', () => { pipe(fpAll, RA.sequence(O.Applicative)); }, opts); bench('true-myth (manual)', () => { const values: number[] = []; for (const m of tmAll) { if (m.isNothing) return TmMaybe.nothing(); values.push((m as { value: number }).value); } return TmMaybe.just(values); }, opts); }); } // --------------------------------------------------------------------------- // Option.all — 20% None (short-circuit) // --------------------------------------------------------------------------- for (const size of SIZES) { const opts = size >= 10_000 ? EXTENDED : STANDARD; const noneIdx = errorIndices(size, 0.2); const nmMixed = Array.from({ length: size }, (_, i) => noneIdx.has(i) ? none() : some(i), ); const tsMixed = Array.from({ length: size }, (_, i) => noneIdx.has(i) ? TsNone : TsSome(i), ); const fpMixed = Array.from({ length: size }, (_, i) => noneIdx.has(i) ? O.none : O.some(i), ); describe(`Option.all — ${size} items, 20% None (short-circuit)`, () => { bench('native-monad', () => { Option.all(nmMixed); }, opts); bench('ts-results-es', () => { TsOption.all(...tsMixed); }, opts); bench('fp-ts', () => { pipe(fpMixed, RA.sequence(O.Applicative)); }, opts); }); } // --------------------------------------------------------------------------- // Option.partition // --------------------------------------------------------------------------- for (const size of SIZES) { const opts = size >= 10_000 ? EXTENDED : STANDARD; const noneIdx = errorIndices(size, 0.2); const nmMixed = Array.from({ length: size }, (_, i) => noneIdx.has(i) ? none() : some(i), ); const fpMixed = Array.from({ length: size }, (_, i) => noneIdx.has(i) ? O.none : O.some(i), ); describe(`Option.partition — ${size} items`, () => { bench('native-monad', () => { Option.partition(nmMixed); }, opts); bench('fp-ts (manual)', () => { const values: number[] = []; let noneCount = 0; for (const o of fpMixed) { if (O.isSome(o)) values.push(o.value); else noneCount++; } return { values, noneCount }; }, opts); }); } // --------------------------------------------------------------------------- // Option.compact // --------------------------------------------------------------------------- for (const size of SIZES) { const opts = size >= 10_000 ? EXTENDED : STANDARD; const noneIdx = errorIndices(size, 0.2); const nmMixed = Array.from({ length: size }, (_, i) => noneIdx.has(i) ? none() : some(i), ); const fpMixed = Array.from({ length: size }, (_, i) => noneIdx.has(i) ? O.none : O.some(i), ); describe(`Option.compact — ${size} items`, () => { bench('native-monad', () => { Option.compact(nmMixed); }, opts); bench('fp-ts', () => { pipe(fpMixed, RA.compact); }, opts); }); } // --------------------------------------------------------------------------- // Option.some / Option.every // --------------------------------------------------------------------------- for (const size of [100, 1_000] as const) { const noneIdx = errorIndices(size, 0.2); const nmMixed = Array.from({ length: size }, (_, i) => noneIdx.has(i) ? none() : some(i), ); const fpMixed = Array.from({ length: size }, (_, i) => noneIdx.has(i) ? O.none : O.some(i), ); describe(`Option.some — ${size} items`, () => { bench('native-monad', () => { Option.some(nmMixed); }, STANDARD); bench('fp-ts (manual)', () => { fpMixed.some(O.isSome); }, STANDARD); }); describe(`Option.every — ${size} items`, () => { bench('native-monad', () => { Option.every(nmMixed); }, STANDARD); bench('fp-ts (manual)', () => { fpMixed.every(O.isSome); }, STANDARD); }); }