import { bench, describe } from 'vitest'; import { STANDARD } from '../helpers/bench-options.js'; import { some, none, TsSome, TsNone, OxSome, OxNone, oxMatch, O, pipe, TmMaybe, } from '../helpers/imports.js'; const double = (x: number) => x * 2; // --------------------------------------------------------------------------- // map — Some path // --------------------------------------------------------------------------- describe('Option.map — Some path', () => { const nm = some(42); const ts = TsSome(42); const ox = OxSome(42); const fp = O.some(42); const tm = TmMaybe.just(42); bench('native-monad', () => { nm.map(double); }, STANDARD); bench('ts-results-es', () => { ts.map(double); }, STANDARD); bench('oxide.ts', () => { ox.map(double); }, STANDARD); bench('fp-ts', () => { pipe(fp, O.map(double)); }, STANDARD); bench('true-myth', () => { tm.map(double); }, STANDARD); }); // --------------------------------------------------------------------------- // map — None path (no-op) // --------------------------------------------------------------------------- describe('Option.map — None path (no-op)', () => { const nm = none(); const ts = TsNone; const ox = OxNone; const fp = O.none; const tm = TmMaybe.nothing(); bench('native-monad', () => { nm.map(double); }, STANDARD); bench('ts-results-es', () => { ts.map(double); }, STANDARD); bench('oxide.ts', () => { ox.map(double); }, STANDARD); bench('fp-ts', () => { pipe(fp, O.map(double)); }, STANDARD); bench('true-myth', () => { tm.map(double); }, STANDARD); }); // --------------------------------------------------------------------------- // flatMap — Some path // --------------------------------------------------------------------------- describe('Option.flatMap — Some path', () => { const nm = some(42); const ts = TsSome(42); const ox = OxSome(42); const fp = O.some(42); const tm = TmMaybe.just(42); bench('native-monad', () => { nm.flatMap(x => some(x * 2)); }, STANDARD); bench('ts-results-es', () => { ts.andThen(x => TsSome(x * 2)); }, STANDARD); bench('oxide.ts', () => { ox.andThen(x => OxSome(x * 2)); }, STANDARD); bench('fp-ts', () => { pipe(fp, O.flatMap(x => O.some(x * 2))); }, STANDARD); bench('true-myth', () => { tm.andThen(x => TmMaybe.just(x * 2)); }, STANDARD); }); // --------------------------------------------------------------------------- // flatMap — None path (no-op) // --------------------------------------------------------------------------- describe('Option.flatMap — None path (no-op)', () => { const nm = none(); const ts = TsNone; const ox = OxNone; const fp = O.none; const tm = TmMaybe.nothing(); bench('native-monad', () => { nm.flatMap(x => some(x * 2)); }, STANDARD); bench('ts-results-es', () => { ts.andThen(x => TsSome(x * 2)); }, STANDARD); bench('oxide.ts', () => { ox.andThen(x => OxSome(x * 2)); }, STANDARD); bench('fp-ts', () => { pipe(fp, O.flatMap(x => O.some(x * 2))); }, STANDARD); bench('true-myth', () => { tm.andThen(x => TmMaybe.just(x * 2)); }, STANDARD); }); // --------------------------------------------------------------------------- // match — Some path // --------------------------------------------------------------------------- describe('Option.match — Some path', () => { const nm = some(42); const ox = OxSome(42); const fp = O.some(42); const tm = TmMaybe.just(42); bench('native-monad', () => { nm.match(x => x * 2, () => 0); }, STANDARD); // ts-results-es: no match bench('oxide.ts', () => { oxMatch(ox, { Some: (x: number) => x * 2, None: () => 0 }); }, STANDARD); bench('fp-ts', () => { pipe(fp, O.match(() => 0, x => x * 2)); }, STANDARD); bench('true-myth', () => { tm.match({ Just: x => x * 2, Nothing: () => 0 }); }, STANDARD); }); // --------------------------------------------------------------------------- // match — None path // --------------------------------------------------------------------------- describe('Option.match — None path', () => { const nm = none(); const ox = OxNone; const fp = O.none; const tm = TmMaybe.nothing(); bench('native-monad', () => { nm.match(x => x * 2, () => 0); }, STANDARD); bench('oxide.ts', () => { oxMatch(ox, { Some: (x: number) => x * 2, None: () => 0 }); }, STANDARD); bench('fp-ts', () => { pipe(fp, O.match(() => 0, x => x * 2)); }, STANDARD); bench('true-myth', () => { tm.match({ Just: x => x * 2, Nothing: () => 0 }); }, STANDARD); }); // --------------------------------------------------------------------------- // filter — Some path (predicate passes) // --------------------------------------------------------------------------- describe('Option.filter — predicate passes', () => { const nm = some(42); const ox = OxSome(42); const fp = O.some(42); bench('native-monad', () => { nm.filter(x => x > 0); }, STANDARD); // ts-results-es: no filter bench('oxide.ts', () => { ox.filter(x => x > 0); }, STANDARD); bench('fp-ts', () => { pipe(fp, O.filter(x => x > 0)); }, STANDARD); // true-myth: no filter on Maybe }); // --------------------------------------------------------------------------- // filter — predicate fails // --------------------------------------------------------------------------- describe('Option.filter — predicate fails', () => { const nm = some(-1); const ox = OxSome(-1); const fp = O.some(-1); bench('native-monad', () => { nm.filter(x => x > 0); }, STANDARD); bench('oxide.ts', () => { ox.filter(x => x > 0); }, STANDARD); bench('fp-ts', () => { pipe(fp, O.filter(x => x > 0)); }, STANDARD); });