diff --git a/.fslckout b/.fslckout new file mode 100644 index 0000000..181ea9d Binary files /dev/null and b/.fslckout differ diff --git a/applicable.ts b/applicable.ts index 6dc5678..4dd98e2 100644 --- a/applicable.ts +++ b/applicable.ts @@ -39,7 +39,86 @@ export function getApplicableCombinable( ) => Combinable<$> { return ( { combine }: Combinable, - ): Combinable<$> => ({ - combine: (second) => (first) => apply(first)(map(combine)(second)), - }); + ): Combinable<$> => { + const _map = map(combine); + return { + combine: (second) => (first) => apply(first)(_map(second)), + }; + }; +} + +/** + * Compose two Applicables into a new apply function. + * + * @since 2.0.0 + */ +export function apply( + U: Applicable, + V: Applicable, +): < + A, + B = never, + C = never, + D = unknown, + E = unknown, + J = never, + K = never, + L = unknown, + M = unknown, +>( + uva: $, J, K], [L], [M]>, +) => ( + uvfai: $ I, B, C], [D], [E]>, J, K], [L], [M]>, +) => $, J, K], [L], [M]> { + return < + A, + B = never, + C = never, + D = unknown, + E = unknown, + J = never, + K = never, + L = unknown, + M = unknown, + >(uva: $, J, K], [L], [M]>) => + ( + uvfai: $ I, B, C], [D], [E]>, J, K], [L], [M]>, + ): $, J, K], [L], [M]> => { + return U.apply(uva)( + U.map( + (vfai: $ I, B, C], [D], [E]>) => + (va: $) => V.apply(va)(vfai), + )(uvfai), + ); + }; +} + +/** + * @since 2.0.0 + */ +export function applyFirst( + U: Applicable, +): ( + second: $, +) => (first: $) => $ { + return ( + second: $, + ) => + (first: $): $ => + U.apply(second)(U.map((a: A) => (_: I) => a)(first)); +} + +/** + * @since 2.0.0 + */ +export function applySecond( + U: Applicable, +): ( + second: $, +) => (first: $) => $ { + return ( + second: $, + ) => + (first: $): $ => + U.apply(second)(U.map(() => (i: I) => i)(first)); } diff --git a/array.ts b/array.ts index 0a7e6e3..77b37f0 100644 --- a/array.ts +++ b/array.ts @@ -9,6 +9,7 @@ import type { $, AnySub, Intersect, Kind, Out } from "./kind.ts"; import type { Applicable } from "./applicable.ts"; +import type { Combinable } from "./combinable.ts"; import type { Comparable } from "./comparable.ts"; import type { Either } from "./either.ts"; import type { Filterable } from "./filterable.ts"; @@ -17,12 +18,14 @@ import type { Initializable } from "./initializable.ts"; import type { Mappable } from "./mappable.ts"; import type { Option } from "./option.ts"; import type { Pair } from "./pair.ts"; -import type { Reducible } from "./reducible.ts"; +import type { Foldable } from "./foldable.ts"; import type { Showable } from "./showable.ts"; import type { Sortable } from "./sortable.ts"; import type { Traversable } from "./traversable.ts"; import type { Wrappable } from "./wrappable.ts"; +import { createBind, createTap } from "./flatmappable.ts"; +import { createBindTo } from "./mappable.ts"; import { pair } from "./pair.ts"; import { isRight } from "./either.ts"; import { fromCompare } from "./comparable.ts"; @@ -30,9 +33,6 @@ import { fromSort, sign } from "./sortable.ts"; import { isSome, none, some } from "./option.ts"; import { identity, pipe } from "./fn.ts"; -const NameReadonlyArray = "ReadonlyArray"; -type NameReadonlyArray = typeof NameReadonlyArray; - /** * This type can be used as a placeholder for an array of any type. * @@ -71,7 +71,6 @@ export type AnyNonEmptyArray = NonEmptyArray; * @since 2.0.0 */ export interface KindArray extends Kind { - readonly name: NameReadonlyArray; readonly kind: ReadonlyArray>; } @@ -412,7 +411,7 @@ export function map( * * const result = pipe( * A.range(5, 1), - * A.reduce((sum, value, index) => sum + value + index, 0), + * A.fold((sum, value, index) => sum + value + index, 0), * ); * // 0 + 0 + 0 = 0 * // 0 + 1 + 1 = 2 @@ -424,7 +423,7 @@ export function map( * * @since 2.0.0 */ -export function reduce( +export function fold( foao: (o: O, a: A, i: number) => O, o: O, ): (ua: ReadonlyArray) => O { @@ -803,7 +802,7 @@ export function traverse( favi: (a: A, i: number) => $, ): (ua: ReadonlyArray) => $, J, K], [L], [M]> => { const pusher = (is: I[]) => (i: I) => [...is, i]; - return reduce( + return fold( (vis, a: A, index) => pipe( vis, @@ -1129,7 +1128,7 @@ export function deleteAt(index: number) { * sort(ordNumber)([3, 1, 2]) * // [1, 2, 3] * - * @category combinators + * @since 2.0.0 */ export function sort( O: Sortable, @@ -1283,6 +1282,15 @@ export function zip>( } } +/** + * @since 2.0.0 + */ +export function getCombinableArray(): Combinable> { + return { + combine, + }; +} + /** * Given an instance Comparable create a Comparable>. * @@ -1434,14 +1442,14 @@ export const MappableArray: Mappable = { map }; /** * @since 2.0.0 */ -export const ReducibleArray: Reducible = { reduce }; +export const FoldableArray: Foldable = { fold }; /** * @since 2.0.0 */ export const TraversableArray: Traversable = { map, - reduce, + fold, traverse, }; @@ -1449,3 +1457,18 @@ export const TraversableArray: Traversable = { * @since 2.0.0 */ export const WrappableArray: Wrappable = { wrap }; + +/** + * @since 2.0.0 + */ +export const tap = createTap(FlatmappableArray); + +/** + * @since 2.0.0 + */ +export const bind = createBind(FlatmappableArray); + +/** + * @since 2.0.0 + */ +export const bindTo = createBindTo(MappableArray); diff --git a/async.ts b/async.ts index cfcb6a8..e219d93 100644 --- a/async.ts +++ b/async.ts @@ -1,27 +1,55 @@ +/** + * This file contains the Async algebraic data type. Async is a lazy, + * asynchronous adt that is useful for encapsulating anything from file reads + * and network requests to timers and loops. + * + * @module Async + * @since 2.0.0 + */ + import type { Kind, Out } from "./kind.ts"; import type { Applicable } from "./applicable.ts"; +import type { Combinable } from "./combinable.ts"; +import type { Initializable } from "./initializable.ts"; import type { Flatmappable } from "./flatmappable.ts"; import type { Mappable } from "./mappable.ts"; import type { Sync } from "./sync.ts"; import type { Wrappable } from "./wrappable.ts"; +import { createBindTo } from "./mappable.ts"; +import { createBind, createTap } from "./flatmappable.ts"; import { resolve, wait } from "./promise.ts"; import { handleThrow } from "./fn.ts"; +/** + * @since 2.0.0 + */ export type Async = Sync>; +/** + * @since 2.0.0 + */ export interface KindAsync extends Kind { readonly kind: Async>; } +/** + * @since 2.0.0 + */ export function delay(ms: number): (ma: Async) => Async { return (ta) => () => wait(ms).then(ta); } +/** + * @since 2.0.0 + */ export function fromSync(fa: Sync): Async { return () => resolve(fa()); } +/** + * @since 2.0.0 + */ export function tryCatch( fasr: (...as: AS) => A | PromiseLike, onThrow: (e: unknown, as: AS) => A, @@ -36,41 +64,107 @@ export function tryCatch( }; } +/** + * @since 2.0.0 + */ export function wrap(a: A): Async { return () => resolve(a); } +/** + * @since 2.0.0 + */ export function map(fai: (a: A) => I): (ta: Async) => Async { return (ta) => () => ta().then(fai); } +/** + * @since 2.0.0 + */ export function apply( ua: Async, ): (ufai: Async<(a: A) => I>) => Async { return (ufai) => () => Promise.all([ufai(), ua()]).then(([fai, a]) => fai(a)); } +/** + * @since 2.0.0 + */ export function applySequential( ua: Async, ): (ufai: Async<(a: A) => I>) => Async { return (ufai) => async () => (await ufai())(await ua()); } +/** + * @since 2.0.0 + */ export function flatmap( fati: (a: A) => Async, ): (ta: Async) => Async { return (ta) => () => ta().then((a) => fati(a)()); } +/** + * @since 2.0.0 + */ +export function getCombinableAsync( + { combine }: Combinable, +): Combinable> { + return { + combine: (second) => (first) => async () => + combine(await second())(await first()), + }; +} + +/** + * @since 2.0.0 + */ +export function getInitializableAsync( + I: Initializable, +): Initializable> { + return { + init: () => async () => await I.init(), + ...getCombinableAsync(I), + }; +} + +/** + * @since 2.0.0 + */ export const WrappableAsync: Wrappable = { wrap }; +/** + * @since 2.0.0 + */ export const ApplicableAsync: Applicable = { apply, map, wrap }; +/** + * @since 2.0.0 + */ export const MappableAsync: Mappable = { map }; +/** + * @since 2.0.0 + */ export const FlatmappableAsync: Flatmappable = { apply, flatmap, map, wrap, }; + +/** + * @since 2.0.0 + */ +export const tap = createTap(FlatmappableAsync); + +/** + * @since 2.0.0 + */ +export const bind = createBind(FlatmappableAsync); + +/** + * @since 2.0.0 + */ +export const bindTo = createBindTo(MappableAsync); diff --git a/async_either.ts b/async_either.ts index acb76e3..770bc98 100644 --- a/async_either.ts +++ b/async_either.ts @@ -5,11 +5,13 @@ * safety. * * @module AsyncEither - * * @since 2.0.0 */ + import type { Kind, Out } from "./kind.ts"; +import type { Applicable } from "./applicable.ts"; import type { Bimappable } from "./bimappable.ts"; +import type { Combinable } from "./combinable.ts"; import type { Either } from "./either.ts"; import type { Flatmappable } from "./flatmappable.ts"; import type { Async } from "./async.ts"; @@ -364,6 +366,27 @@ export function match( // (ta: AsyncEither): AsyncEither => // () => Promise.race([ta(), wait(ms).then(flow(onTimeout, E.left))]); +/** + * @since 2.0.0 + */ +export function getCombinableAsyncEither(CA: Combinable, CB: Combinable): Combinable> { + const combinableEither = E.getRightInitializable + + return { + combine: second => first => async () => + + } +} + +/** + * @since 2.0.0 + */ +export const ApplicableAsyncEither: Applicable = { + apply, + map, + wrap, +}; + /** * @since 2.0.0 */ diff --git a/async_iterable.ts b/async_iterable.ts index 0a59045..fa93f77 100644 --- a/async_iterable.ts +++ b/async_iterable.ts @@ -222,15 +222,15 @@ export function partitionMap( }; } -export function reduce( - reducer: (value: O, accumulator: A, index: number) => O, +export function fold( + foldr: (value: O, accumulator: A, index: number) => O, initial: O, ): (ta: AsyncIterable) => Promise { return async (ta) => { let index = 0; let result = initial; for await (const value of ta) { - result = reducer(result, value, index++); + result = foldr(result, value, index++); } return result; }; @@ -267,7 +267,7 @@ export function takeWhile( } export function scan( - reducer: (accumulator: O, value: A, index: number) => O, + foldr: (accumulator: O, value: A, index: number) => O, initial: O, ): (ta: AsyncIterable) => AsyncIterable { return (ta) => @@ -275,7 +275,7 @@ export function scan( let result = initial; let index = 0; for await (const a of ta) { - result = reducer(result, a, index++); + result = foldr(result, a, index++); yield result; } }); diff --git a/combinable.ts b/combinable.ts index 72368e9..a2c83a2 100644 --- a/combinable.ts +++ b/combinable.ts @@ -364,7 +364,7 @@ export function constant(a: A): Combinable { /** * Given a Combinable, create a function that will * iterate through an array of values and combine - * them. This is not much more than Array.reduce(combine). + * them. This is not much more than Array.fold(combine). * * @example * ```ts diff --git a/datum.ts b/datum.ts index caf3ff5..156e1fa 100644 --- a/datum.ts +++ b/datum.ts @@ -191,7 +191,7 @@ export function alt(tb: Datum): (ta: Datum) => Datum { return (ta) => isSome(ta) ? ta : tb; } -export function reduce( +export function fold( foao: (o: O, a: A) => O, o: O, ): (ta: Datum) => O { @@ -279,6 +279,6 @@ export const FlatmappableDatum: Flatmappable = { export const TraversableDatum: Traversable = { map, - reduce, + fold, traverse, }; diff --git a/decoder.ts b/decoder.ts index 86e2308..7f2ca9a 100644 --- a/decoder.ts +++ b/decoder.ts @@ -474,9 +474,9 @@ export function manyErr( * (_, err) => countErrors(err), * (_, __, err) => countErrors(err), * (_, __, err) => countErrors(err), - * A.reduce((acc, err) => acc + countErrors(err), 0), - * A.reduce((acc, err) => acc + countErrors(err), 0), - * A.reduce((acc, err) => acc + countErrors(err), 0), + * A.fold((acc, err) => acc + countErrors(err), 0), + * A.fold((acc, err) => acc + countErrors(err), 0), + * A.fold((acc, err) => acc + countErrors(err), 0), * ); * * const result1 = countErrors(D.leafErr(1, "expected string")); // 1 diff --git a/either.ts b/either.ts index eb7afb3..b7bc153 100644 --- a/either.ts +++ b/either.ts @@ -8,7 +8,7 @@ import type { Failable } from "./failable.ts"; import type { Flatmappable } from "./flatmappable.ts"; import type { Mappable } from "./mappable.ts"; import type { Predicate } from "./predicate.ts"; -import type { Reducible } from "./reducible.ts"; +import type { Foldable } from "./foldable.ts"; import type { Refinement } from "./refinement.ts"; import type { Showable } from "./showable.ts"; import type { Sortable } from "./sortable.ts"; @@ -274,7 +274,7 @@ export function alt( return (ta) => isLeft(ta) ? tb : ta; } -export function reduce( +export function fold( foao: (o: O, a: A) => O, o: O, ): (ta: Either) => O { @@ -316,11 +316,11 @@ export const FlatmappableEither: Flatmappable = { export const MappableEither: Mappable = { map }; -export const ReducibleEither: Reducible = { reduce }; +export const FoldableEither: Foldable = { fold }; export const TraversableEither: Traversable = { map, - reduce, + fold, traverse, }; diff --git a/examples/hkts.ts b/examples/hkts.ts index adfa3ba..969bf95 100644 --- a/examples/hkts.ts +++ b/examples/hkts.ts @@ -1,5 +1,5 @@ // deno-lint-ignore-file no-explicit-any ban-types -import { pipe } from "../fns.ts"; +import { pipe } from "../fn.ts"; /** * This is here just to show a different path for @@ -51,23 +51,22 @@ export type Primitives = export type $ = T extends Fix ? F : T extends _ ? S[N] - : T extends Primitives ? T : T extends any[] ? { [K in keyof T]: $ } : T extends (...as: infer AS) => infer R ? (...as: $) => $ : T extends Promise ? Promise<$> : T extends object ? { [K in keyof T]: $ } - : T extends unknown ? never - : T; + : T extends Primitives ? T + : never; // --- // Type Classes // --- -export type FunctorFn = ( +export type FunctorFn = ( fai: (a: A) => I, -) => (ta: $) => $; +) => (ta: $) => $; -export type ApplyFn = ( +export type ApplyFn = ( tfai: $ I]>, ) => (ta: $) => $; @@ -131,14 +130,25 @@ export const traversePromise = traverse(ApplicativePromise); export type Left = { tag: "Left"; left: B }; export type Right = { tag: "Right"; right: A }; -export type Either = Left | Right; +export type Either = Left | Right; export const left = (left: B): Either => ({ tag: "Left", left }); export const right = (right: A): Either => ({ tag: "Right", right, }); -export const ApplicativeEither: Applicative> = { +export const mapEither: FunctorFn> = (fai) => (ua) => + ua.tag === "Right" ? right(fai(ua.right)) : ua; +export const mapEitherT1 = pipe( + right(1), + mapEither((n) => n + 1), +); +export const mapEitherT2 = pipe( + left(1), + mapEither((n: number) => n + 1), +); + +export const ApplicativeEither: Applicative> = { of: right, ap: (tfai: Either I>) => (ta: Either) => ta.tag === "Left" diff --git a/flake.lock b/flake.lock index c4c91c8..dcb737d 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1692799911, - "narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=", + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "owner": "numtide", "repo": "flake-utils", - "rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "type": "github" }, "original": { @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1693844670, - "narHash": "sha256-t69F2nBB8DNQUWHD809oJZJVE+23XBrth4QZuVd6IE0=", + "lastModified": 1696419054, + "narHash": "sha256-EdR+dIKCfqL3voZUDYwcvgRDOektQB9KbhBVcE0/3Mo=", "owner": "nixos", "repo": "nixpkgs", - "rev": "3c15feef7770eb5500a4b8792623e2d6f598c9c1", + "rev": "7131f3c223a2d799568e4b278380cd9dac2b8579", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 796a1aa..5b9ba3f 100644 --- a/flake.nix +++ b/flake.nix @@ -22,7 +22,7 @@ }; shell = with pkgs; mkShell { - buildInputs = [ deno nodejs jq lcov ]; + buildInputs = [ deno nodejs jq lcov jujutsu ]; }; in diff --git a/foldable.ts b/foldable.ts new file mode 100644 index 0000000..b4d73a8 --- /dev/null +++ b/foldable.ts @@ -0,0 +1,38 @@ +/** + * Foldable is a structure that allows a function to all values inside of a + * structure. The reduction is accumulative and ordered. + * + * @module Foldable + * @since 2.0.0 + */ + +import type { $, Hold, Kind } from "./kind.ts"; +import type { Initializable } from "./initializable.ts"; + +/** + * A Foldable structure has the method fold. + * + * @since 2.0.0 + */ +export interface Foldable extends Hold { + readonly fold: ( + reducer: (accumulator: O, value: A) => O, + accumulator: O, + ) => ( + ua: $, + ) => O; +} + +/** + * @experimental + * @since 2.0.0 + */ +export function collect( + { fold }: Foldable, + { combine, init }: Initializable, +): ( + ua: $, +) => A { + return (ua) => + fold((first, second) => combine(second)(first), init())(ua); +} diff --git a/free.ts b/free.ts index ed4e552..6a116fc 100644 --- a/free.ts +++ b/free.ts @@ -89,15 +89,15 @@ export function apply(ua: Free): (ufai: Free<(a: A) => I>) => Free { return (ufai) => pipe(ufai, flatmap(flow(map, (fn) => fn(ua)))); } -export function reduce( - reducer: (value: A, accumulator: O) => O, +export function fold( + foldr: (value: A, accumulator: O) => O, initial: O, ): (ua: Free) => O { // :( let result = initial; const go: (ua: Free) => O = match( (value) => { - result = reducer(value, result); + result = foldr(value, result); return result; }, (first, second) => { diff --git a/initializable.ts b/initializable.ts index 3f7a9c7..366db4f 100644 --- a/initializable.ts +++ b/initializable.ts @@ -148,7 +148,7 @@ export function intercalcate(middle: A) { /** * Given an Initializable, create a function that will * iterate through an array of values and combine - * them. This is not much more than Array.reduce(combine). + * them. This is not much more than Array.fold(combine). * * @example * ```ts diff --git a/iterable.ts b/iterable.ts index 4d3a267..850f477 100644 --- a/iterable.ts +++ b/iterable.ts @@ -143,14 +143,14 @@ export function forEach(fa: (a: A) => void): (ta: Iterable) => void { /** * @since 2.0.0 */ -export function reduce( - reducer: (accumulator: O, value: A) => O, +export function fold( + foldr: (accumulator: O, value: A) => O, initial: O, ) { return (ua: Iterable): O => { let out = initial; for (const a of ua) { - out = reducer(out, a); + out = foldr(out, a); } return out; }; @@ -160,7 +160,7 @@ export function reduce( * @since 2.0.0 */ export function scan( - reducer: (accumulator: O, value: A, index: number) => O, + foldr: (accumulator: O, value: A, index: number) => O, initial: O, ): (ta: Iterable) => Iterable { return (ta) => @@ -168,7 +168,7 @@ export function scan( let result = initial; let index = 0; for (const a of ta) { - result = reducer(result, a, index++); + result = foldr(result, a, index++); yield result; } }); diff --git a/map.ts b/map.ts index 3fd6c70..f82f56b 100644 --- a/map.ts +++ b/map.ts @@ -4,7 +4,7 @@ import type { Combinable } from "./combinable.ts"; import type { Comparable } from "./comparable.ts"; import type { Mappable } from "./mappable.ts"; import type { Option } from "./option.ts"; -import type { Reducible } from "./reducible.ts"; +import type { Foldable } from "./foldable.ts"; import type { Showable } from "./showable.ts"; import type { Sortable } from "./sortable.ts"; @@ -144,14 +144,14 @@ export function values(O: Sortable): (ta: ReadonlyMap) => A[] { return (ta) => Array.from(ta.values()).sort(O.sort); } -export function reduce( - reducer: (accumulator: O, value: A, key: B) => O, +export function fold( + foldr: (accumulator: O, value: A, key: B) => O, initial: O, ) { return (ua: ReadonlyMap): O => { let result = initial; for (const [key, value] of ua.entries()) { - result = reducer(result, value, key); + result = foldr(result, value, key); } return result; }; @@ -306,7 +306,7 @@ export const MappableMap: Mappable = { map }; export const BimappableMap: Bimappable = { map, mapSecond }; -export const ReducibleMap: Reducible = { reduce }; +export const FoldableMap: Foldable = { fold }; export function getShowable( SK: Showable, diff --git a/mod.ts b/mod.ts index fb0923c..0bfa71f 100644 --- a/mod.ts +++ b/mod.ts @@ -32,7 +32,7 @@ export * as pair from "./pair.ts"; export * as predicate from "./predicate.ts"; export * as premappable from "./premappable.ts"; export * as promise from "./promise.ts"; -export * as reducible from "./reducible.ts"; +export * as foldable from "./foldable.ts"; export * as refinement from "./refinement.ts"; export * as schemable from "./schemable.ts"; export * as set from "./set.ts"; diff --git a/optic.ts b/optic.ts index e9487f5..5ee7723 100644 --- a/optic.ts +++ b/optic.ts @@ -1272,7 +1272,7 @@ export function atMap(eq: Comparable): (key: B) => ( /** * Construct a composable optic from a Traversable instance for a Kind T. This - * will reduce the values wrapped in the Kind T into a single Array when viewed. + * will fold the values wrapped in the Kind T into a single Array when viewed. * * @example * ```ts @@ -1305,7 +1305,7 @@ export function traverse( first: Optic>, ) => Optic, S, A> { return compose(fold( - T.reduce((as, a) => [...as, a], A.init()), + T.fold((as, a) => [...as, a], A.init()), T.map, )); } diff --git a/option.ts b/option.ts index e4b2ca4..73a9161 100644 --- a/option.ts +++ b/option.ts @@ -17,7 +17,7 @@ import type { Initializable } from "./initializable.ts"; import type { Mappable } from "./mappable.ts"; import type { Pair } from "./pair.ts"; import type { Predicate } from "./predicate.ts"; -import type { Reducible } from "./reducible.ts"; +import type { Foldable } from "./foldable.ts"; import type { Refinement } from "./refinement.ts"; import type { Showable } from "./showable.ts"; import type { Sortable } from "./sortable.ts"; @@ -615,26 +615,26 @@ export function partitionMap( /** * Reduce over an Option. Since an Option contains at most one value this * function operates a lot like getOrElse. If the passed option is None then it - * returns the initial value, otherwise the reducer function is called with both + * returns the initial value, otherwise the foldr function is called with both * the initial value and the inner A. * * @example * ```ts * import * as O from "./option.ts"; * - * const reduce = O.reduce((n: number, m: number) => n + m, 0); + * const fold = O.fold((n: number, m: number) => n + m, 0); * - * const result1 = reduce(O.some(1)); // 1 - * const result2 = reduce(O.none); // 0 + * const result1 = fold(O.some(1)); // 1 + * const result2 = fold(O.none); // 0 * ``` * * @since 2.0.0 */ -export function reduce( - reducer: (accumulator: O, current: A) => O, +export function fold( + foldr: (accumulator: O, current: A) => O, initial: O, ): (ua: Option) => O { - return (ua) => isSome(ua) ? reducer(initial, ua.value) : initial; + return (ua) => isSome(ua) ? foldr(initial, ua.value) : initial; } /** @@ -697,11 +697,11 @@ export const FilterableOption: Filterable = { }; /** - * The canonical implementation of Reducible for Option. + * The canonical implementation of Foldable for Option. * * @since 2.0.0 */ -export const ReducibleOption: Reducible = { reduce }; +export const FoldableOption: Foldable = { fold }; /** * The canonical implementation of Traversable for Option. @@ -710,7 +710,7 @@ export const ReducibleOption: Reducible = { reduce }; */ export const TraversableOption: Traversable = { map, - reduce, + fold, traverse, }; diff --git a/pair.ts b/pair.ts index 90f8fd2..a1bf662 100644 --- a/pair.ts +++ b/pair.ts @@ -12,7 +12,7 @@ import type { Bimappable } from "./bimappable.ts"; import type { Flatmappable } from "./flatmappable.ts"; import type { Initializable } from "./initializable.ts"; import type { Mappable } from "./mappable.ts"; -import type { Reducible } from "./reducible.ts"; +import type { Foldable } from "./foldable.ts"; import type { Showable } from "./showable.ts"; import type { Traversable } from "./traversable.ts"; @@ -328,22 +328,22 @@ export function unwrap([first]: Pair): A { /** * Reduces a pair with an initial value, also passing - * the second value into the reducer as well. + * the second value into the foldr as well. * * @example * ```ts - * import { pair, reduce } from "./pair.ts"; + * import { pair, fold } from "./pair.ts"; * import { pipe } from "./fn.ts"; * * const result = pipe( * pair(10, 20), - * reduce(Math.max, Number.NEGATIVE_INFINITY), + * fold(Math.max, Number.NEGATIVE_INFINITY), * ); // 20 * ``` * * @since 2.0.0 */ -export function reduce( +export function fold( foao: (acc: O, first: A, second: B) => O, initial: O, ): (ua: Pair) => O { @@ -405,17 +405,17 @@ export const MappablePair: Mappable = { map }; export const BimappablePair: Bimappable = { mapSecond, map }; /** - * The canonical Reducible instance for Pair. Contains the - * reduce method. + * The canonical Foldable instance for Pair. Contains the + * fold method. * * @since 2.0.0 */ -export const ReduciblePair: Reducible = { reduce }; +export const FoldablePair: Foldable = { fold }; /** * @since 2.0.0 */ -export const TraversablePair: Traversable = { map, reduce, traverse }; +export const TraversablePair: Traversable = { map, fold, traverse }; /** * Creates a Showable instance for a pair, wrapping the Showable instances provided diff --git a/record.ts b/record.ts index 9a9de3b..2ce1f40 100644 --- a/record.ts +++ b/record.ts @@ -13,7 +13,7 @@ import type { Applicable } from "./applicable.ts"; import type { Either } from "./either.ts"; import type { Comparable } from "./comparable.ts"; import type { Filterable } from "./filterable.ts"; -import type { Reducible } from "./reducible.ts"; +import type { Foldable } from "./foldable.ts"; import type { Mappable } from "./mappable.ts"; import type { Initializable } from "./initializable.ts"; import type { Option } from "./option.ts"; @@ -217,13 +217,13 @@ export function map( * * const result = pipe( * { one: 1, two: 2 }, - * R.reduce((sum, value) => sum + value, 0), + * R.fold((sum, value) => sum + value, 0), * ); // 3 * ``` * * @since 2.0.0 */ -export function reduce( +export function fold( foao: (o: O, a: A, i: string) => O, o: O, ) { @@ -239,7 +239,7 @@ export function reduce( /** * Collect all values in a ReadonlyRecord into a single * value I by using a Combinable and a mapping function - * from A to I. This is effectively reduce using a Combinable + * from A to I. This is effectively fold using a Combinable * for the initial value. * * @example @@ -260,17 +260,17 @@ export function collect( M: Initializable, ): (fai: (a: A, index: string) => I) => (ua: ReadonlyRecord) => I { return (fai: (a: A, index: string) => I) => { - const reducer = reduce( + const foldr = fold( (i, a: A, index) => M.combine(fai(a, index))(i), M.init(), ); - return (ua: ReadonlyRecord) => reducer(ua); + return (ua: ReadonlyRecord) => foldr(ua); }; } /** * Collect all values in a ReadonlyRecord into a single - * value I by using a Combinable. This is effectively reduce + * value I by using a Combinable. This is effectively fold * using a Combinable for the initial value and combination. * * @example @@ -290,7 +290,7 @@ export function collect( export function collapse( M: Initializable, ): (ua: ReadonlyRecord) => A { - return reduce(uncurry2(M.combine), M.init()); + return fold(uncurry2(M.combine), M.init()); } /** @@ -338,7 +338,7 @@ export function traverse( i: I, ): Record => ({ ...is, [key]: i }); // Interior mutability is used to increase perf - const reducer = ( + const foldr = ( vis: $, J, K], [L], [M]>, a: A, key: string, @@ -349,7 +349,7 @@ export function traverse( A.apply(favi(a, key)), ); - return (ua) => pipe(ua, reduce(reducer, A.wrap({}))); + return (ua) => pipe(ua, fold(foldr, A.wrap({}))); }; } @@ -952,22 +952,22 @@ export const FilterableRecord: Filterable = { export const MappableRecord: Mappable = { map }; /** - * The canonical implementation of Reducible for ReadonlyRecord. It contains - * the method reduce. + * The canonical implementation of Foldable for ReadonlyRecord. It contains + * the method fold. * * @since 2.0.0 */ -export const ReducibleRecord: Reducible = { reduce }; +export const FoldableRecord: Foldable = { fold }; /** * The canonical implementation of Traversable for ReadonlyRecord. It contains - * the methods map, reduce, and traverse. + * the methods map, fold, and traverse. * * @since 2.0.0 */ export const TraversableRecord: Traversable = { map, - reduce, + fold, traverse, }; diff --git a/set.ts b/set.ts index 11d4766..f2ded73 100644 --- a/set.ts +++ b/set.ts @@ -10,7 +10,7 @@ import type { Applicable } from "./applicable.ts"; import type { Either } from "./either.ts"; import type { Comparable } from "./comparable.ts"; import type { Filterable } from "./filterable.ts"; -import type { Reducible } from "./reducible.ts"; +import type { Foldable } from "./foldable.ts"; import type { Mappable } from "./mappable.ts"; import type { Flatmappable } from "./flatmappable.ts"; import type { Combinable } from "./combinable.ts"; @@ -677,13 +677,13 @@ export function partitionMap( * * const result = pipe( * set, - * S.reduce((previous, current) => previous + current, 0), + * S.fold((previous, current) => previous + current, 0), * ); // 10 * ``` * * @since 2.0.0 */ -export function reduce( +export function fold( foao: (o: O, a: A) => O, o: O, ): (ua: ReadonlySet) => O { @@ -736,7 +736,7 @@ export function traverse( return ( favi: (a: A) => $, ): (ua: ReadonlySet) => $, J, K], [L], [M]> => - reduce( + fold( (vis, a) => pipe(vis, A.map(unsafeAdd), A.apply(favi(a))), A.wrap(init() as Set), ); @@ -785,22 +785,22 @@ export const FilterableSet: Filterable = { }; /** - * The canonical implementation of Reducible for ReadonlySet. It contains - * the method reduce. + * The canonical implementation of Foldable for ReadonlySet. It contains + * the method fold. * * @since 2.0.0 */ -export const ReducibleSet: Reducible = { reduce }; +export const FoldableSet: Foldable = { fold }; /** * The canonical implementation of Traversable for ReadonlySet. It contains - * the methods map, reduce, and traverse. + * the methods map, fold, and traverse. * * @since 2.0.0 */ export const TraversableSet: Traversable = { map, - reduce, + fold, traverse, }; diff --git a/sync.ts b/sync.ts index 1ad20d5..2508b03 100644 --- a/sync.ts +++ b/sync.ts @@ -2,7 +2,7 @@ import type { $, Kind, Out } from "./kind.ts"; import type { Applicable } from "./applicable.ts"; import type { Flatmappable } from "./flatmappable.ts"; import type { Mappable } from "./mappable.ts"; -import type { Reducible } from "./reducible.ts"; +import type { Foldable } from "./foldable.ts"; import type { Traversable } from "./traversable.ts"; import type { Wrappable } from "./wrappable.ts"; @@ -32,7 +32,7 @@ export function flatmap( return (ta) => flow(ta, fati, (x) => x()); } -export function reduce( +export function fold( foao: (o: O, a: A) => O, o: O, ): (ta: Sync) => O { @@ -60,6 +60,6 @@ export const FlatmappableSync: Flatmappable = { wrap, }; -export const ReducibleSync: Reducible = { reduce }; +export const FoldableSync: Foldable = { fold }; -export const TraversableSync: Traversable = { map, reduce, traverse }; +export const TraversableSync: Traversable = { map, fold, traverse }; diff --git a/sync_either.ts b/sync_either.ts index 7093ef7..4933654 100644 --- a/sync_either.ts +++ b/sync_either.ts @@ -3,7 +3,7 @@ import type { Bimappable } from "./bimappable.ts"; import type { Applicable } from "./applicable.ts"; import type { Mappable } from "./mappable.ts"; import type { Failable } from "./failable.ts"; -import type { Reducible } from "./reducible.ts"; +import type { Foldable } from "./foldable.ts"; import type { Flatmappable } from "./flatmappable.ts"; import type { Sync } from "./sync.ts"; import type { Either } from "./either.ts"; @@ -97,7 +97,7 @@ export function alt( return (ta) => flow(ta, E.match(tb, E.right)); } -export function reduce( +export function fold( foao: (o: O, a: A) => O, o: O, ): (ta: SyncEither) => O { @@ -134,4 +134,4 @@ export const FailableSyncEither: Failable = { wrap, }; -export const ReducibleSyncEither: Reducible = { reduce }; +export const FoldableSyncEither: Foldable = { fold }; diff --git a/testing/applicable.test.ts b/testing/applicable.test.ts index d068570..1746dd2 100644 --- a/testing/applicable.test.ts +++ b/testing/applicable.test.ts @@ -17,3 +17,43 @@ Deno.test("Applicable getApplicableCombinable", () => { assertEquals(combineAll(O.some(1), O.none), O.none); assertEquals(combineAll(O.some(1), O.some(1)), O.some(2)); }); + +Deno.test("Applicable apply", () => { + const apply = A.apply(O.ApplicableOption, O.ApplicableOption); + const o1: O.Option> = O.none; + const o2: O.Option> = O.some(O.none); + const o3: O.Option> = O.some(O.some(1)); + const f1: O.Option [number, number]>> = O.none; + const f2: O.Option [number, number]>> = O.some( + O.none, + ); + const f3: O.Option [number, number]>> = O.some( + O.some((n) => [n, n + 1]), + ); + + assertEquals(apply(o1)(f1), O.none); + assertEquals(apply(o1)(f2), O.none); + assertEquals(apply(o1)(f3), O.none); + assertEquals(apply(o2)(f1), O.none); + assertEquals(apply(o2)(f2), O.some(O.none)); + assertEquals(apply(o2)(f3), O.some(O.none)); + assertEquals(apply(o3)(f1), O.none); + assertEquals(apply(o3)(f2), O.some(O.none)); + assertEquals(apply(o3)(f3), O.some(O.some([1, 2]))); +}); + +Deno.test("Applicable applyFirst", () => { + const applyFirst = A.applyFirst(O.ApplicableOption); + assertEquals(applyFirst(O.none)(O.none), O.none); + assertEquals(applyFirst(O.none)(O.some(1)), O.none); + assertEquals(applyFirst(O.some(2))(O.none), O.none); + assertEquals(applyFirst(O.some(2))(O.some(1)), O.some(1)); +}); + +Deno.test("Applicable applySecond", () => { + const applySecond = A.applySecond(O.ApplicableOption); + assertEquals(applySecond(O.none)(O.none), O.none); + assertEquals(applySecond(O.none)(O.some(1)), O.none); + assertEquals(applySecond(O.some(2))(O.none), O.none); + assertEquals(applySecond(O.some(2))(O.some(1)), O.some(2)); +}); diff --git a/testing/array.test.ts b/testing/array.test.ts index 62cac8d..050c9f1 100644 --- a/testing/array.test.ts +++ b/testing/array.test.ts @@ -113,8 +113,8 @@ Deno.test("Array flatmap", () => { ]); }); -Deno.test("Array reduce", () => { - assertEquals(pipe([1, 2, 3], A.reduce((a, b) => a + b, 0)), 6); +Deno.test("Array fold", () => { + assertEquals(pipe([1, 2, 3], A.fold((a, b) => a + b, 0)), 6); }); Deno.test("Array traverse", () => { @@ -128,7 +128,7 @@ Deno.test("Array indexedMap", () => { }); Deno.test("Array indexedReduce", () => { - assertEquals(pipe([1, 2, 3], A.reduce((a, b, i) => a + b + i, 0)), 9); + assertEquals(pipe([1, 2, 3], A.fold((a, b, i) => a + b + i, 0)), 9); }); Deno.test("Array indexedTraverse", () => { @@ -308,6 +308,11 @@ Deno.test("Array range", () => { assertEquals(A.range(-1, 1, 1), []); }); +Deno.test("Array getCombinableArray", () => { + const { combine } = A.getCombinableArray(); + assertStrictEquals(combine, A.combine); +}); + Deno.test("Array getComparableArray", () => { const eq = A.getComparableArray(ComparableBoolean); const values = [true, false]; @@ -354,3 +359,29 @@ Deno.test("Array getShowableArray", () => { assertEquals(show.show([]), "ReadonlyArray[]"); assertEquals(show.show([1, 2, 3]), "ReadonlyArray[1, 2, 3]"); }); + +Deno.test("Array tap", () => { + const out: number[] = []; + pipe( + A.range(3), + A.tap((n) => out.push(n)), + ); + assertEquals(out, A.range(3)); +}); + +Deno.test("Array bind", () => { + assertEquals( + pipe( + A.range(2), + A.bindTo("a"), + A.bind("b", ({ a }) => [a, a + 1]), + ), + [{ a: 0, b: 0 }, { a: 0, b: 1 }, { a: 1, b: 1 }, { a: 1, b: 2 }], + ); +}); + +Deno.test("Array bindTo", () => { + assertEquals(pipe(A.range(2), A.bindTo("range")), [{ range: 0 }, { + range: 1, + }]); +}); diff --git a/testing/async.test.ts b/testing/async.test.ts index a5ddcab..5095b3b 100644 --- a/testing/async.test.ts +++ b/testing/async.test.ts @@ -1,6 +1,7 @@ import { assertEquals } from "https://deno.land/std@0.103.0/testing/asserts.ts"; import * as A from "../async.ts"; +import * as N from "../number.ts"; import { pipe } from "../fn.ts"; const add = (n: number) => n + 1; @@ -64,21 +65,54 @@ Deno.test("Async apSeq", async () => { ); }); -// Deno.test("Async Do, bind, bindTo", () => { -// assertEquals( -// pipe( -// A.Do(), -// A.bind("one", () => A.wrap(1)), -// A.bind("two", ({ one }) => A.wrap(one + one)), -// A.map(({ one, two }) => one + two), -// ), -// A.wrap(3), -// ); -// assertEquals( -// pipe( -// A.wrap(1), -// A.bindTo("one"), -// ), -// A.wrap({ one: 1 }), -// ); -// }); +Deno.test("Async getCombinableAsync", async () => { + const { combine } = A.getCombinableAsync(N.InitializableNumberSum); + assertEquals( + await pipe( + A.wrap(1), + combine(A.wrap(2)), + )(), + 3, + ); +}); + +Deno.test("Async getInitializableAsync", async () => { + const { init, combine } = A.getInitializableAsync(N.InitializableNumberSum); + assertEquals(await init()(), 0); + assertEquals( + await pipe( + A.wrap(1), + combine(A.wrap(2)), + )(), + 3, + ); +}); + +Deno.test("Async tap", async () => { + let out: null | number = null; + await pipe( + A.wrap(1), + A.tap((n) => out = n), + )(); + assertEquals(out, 1); +}); + +Deno.test("Async bind", async () => { + assertEquals( + await pipe( + A.wrap({ a: 1 }), + A.bind("b", ({ a }) => A.wrap(a + 1)), + )(), + { a: 1, b: 2 }, + ); +}); + +Deno.test("Async bindTo", async () => { + assertEquals( + await pipe( + A.wrap(1), + A.bindTo("a"), + )(), + { a: 1 }, + ); +}); diff --git a/testing/async_iterable.test.ts b/testing/async_iterable.test.ts index ff86129..6aae2d6 100644 --- a/testing/async_iterable.test.ts +++ b/testing/async_iterable.test.ts @@ -149,11 +149,11 @@ Deno.test("AsyncIterable partitionMap", async () => { assertEquals(await AI.collect(second), [0, 1]); }); -Deno.test("AsyncIterable reduce", async () => { +Deno.test("AsyncIterable fold", async () => { assertEquals( await pipe( AI.range(3), - AI.reduce((value, sum) => value + sum, 0), + AI.fold((value, sum) => value + sum, 0), ), 3, ); diff --git a/testing/datum.test.ts b/testing/datum.test.ts index fc9a04a..6526725 100644 --- a/testing/datum.test.ts +++ b/testing/datum.test.ts @@ -290,13 +290,13 @@ Deno.test("Datum alt", () => { assertEquals(pipe(D.refresh(1), D.alt(D.refresh(2))), D.refresh(1)); }); -Deno.test("Datum reduce", () => { - const reduce = D.reduce((o: number, a: number) => o + a, 0); +Deno.test("Datum fold", () => { + const fold = D.fold((o: number, a: number) => o + a, 0); - assertEquals(reduce(D.initial), 0); - assertEquals(reduce(D.pending), 0); - assertEquals(reduce(D.replete(1)), 1); - assertEquals(reduce(D.refresh(1)), 1); + assertEquals(fold(D.initial), 0); + assertEquals(fold(D.pending), 0); + assertEquals(fold(D.replete(1)), 1); + assertEquals(fold(D.refresh(1)), 1); }); Deno.test("Datum traverse", () => { diff --git a/testing/decoder.test.ts b/testing/decoder.test.ts index cc33b0e..ba4fd1b 100644 --- a/testing/decoder.test.ts +++ b/testing/decoder.test.ts @@ -162,9 +162,9 @@ Deno.test("DecodeError match", () => { (_, err) => countErrors(err), (_, __, err) => countErrors(err), (_, __, err) => countErrors(err), - A.reduce((acc, err) => acc + countErrors(err), 0), - A.reduce((acc, err) => acc + countErrors(err), 0), - A.reduce((acc, err) => acc + countErrors(err), 0), + A.fold((acc, err) => acc + countErrors(err), 0), + A.fold((acc, err) => acc + countErrors(err), 0), + A.fold((acc, err) => acc + countErrors(err), 0), ); assertEquals(countErrors(leaf), 1); diff --git a/testing/either.test.ts b/testing/either.test.ts index a60d3ba..7506525 100644 --- a/testing/either.test.ts +++ b/testing/either.test.ts @@ -185,11 +185,11 @@ Deno.test("Either getRightInitializable", () => { assertEquals(Initializable.init(), E.right(N.InitializableNumberSum.init())); }); -Deno.test("Either reduce", () => { - const reduce = E.reduce((o: number, i: number) => o + i, 0); +Deno.test("Either fold", () => { + const fold = E.fold((o: number, i: number) => o + i, 0); - assertEquals(reduce(E.left("adsf")), 0); - assertEquals(reduce(E.right(1)), 1); + assertEquals(fold(E.left("adsf")), 0); + assertEquals(fold(E.right(1)), 1); }); Deno.test("Either map", () => { diff --git a/testing/foldable.test.ts b/testing/foldable.test.ts new file mode 100644 index 0000000..01904d7 --- /dev/null +++ b/testing/foldable.test.ts @@ -0,0 +1,11 @@ +import { assertEquals } from "https://deno.land/std@0.103.0/testing/asserts.ts"; + +import * as R from "../foldable.ts"; +import * as A from "../array.ts"; +import * as N from "../number.ts"; + +Deno.test("Foldable collect", () => { + const collect = R.collect(A.FoldableArray, N.InitializableNumberSum); + assertEquals(collect([]), 0); + assertEquals(collect([1, 2, 3, 4]), 10); +}); diff --git a/testing/free.test.ts b/testing/free.test.ts index 4fb3baa..5b83c0e 100644 --- a/testing/free.test.ts +++ b/testing/free.test.ts @@ -112,9 +112,9 @@ Deno.test("Free apply", () => { ); }); -Deno.test("Free reduce", () => { +Deno.test("Free fold", () => { assertEquals( - pipe(F.link(F.node(1), F.node(1)), F.reduce((n, m) => n + m, 0)), + pipe(F.link(F.node(1), F.node(1)), F.fold((n, m) => n + m, 0)), 2, ); }); diff --git a/testing/iterable.test.ts b/testing/iterable.test.ts index 9bccf4a..3da05af 100644 --- a/testing/iterable.test.ts +++ b/testing/iterable.test.ts @@ -73,11 +73,11 @@ Deno.test("Iterable forEach", () => { assertEquals(results, [0, 1, 2]); }); -Deno.test("Iterable reduce", () => { +Deno.test("Iterable fold", () => { assertEquals( pipe( I.range(3), - I.reduce((n, m) => n + m, 0), + I.fold((n, m) => n + m, 0), ), 3, ); diff --git a/testing/map.test.ts b/testing/map.test.ts index d3832e3..aa73f9e 100644 --- a/testing/map.test.ts +++ b/testing/map.test.ts @@ -3,7 +3,7 @@ import { assertEquals } from "https://deno.land/std/testing/asserts.ts"; import * as M from "../map.ts"; import * as O from "../option.ts"; import * as N from "../number.ts"; -import * as R from "../reducible.ts"; +import * as R from "../foldable.ts"; import { pipe } from "../fn.ts"; Deno.test("Map init", () => { @@ -97,8 +97,8 @@ Deno.test("Map values", () => { assertEquals(pipe(tb, values), []); }); -Deno.test("Map reduce", () => { - const collect = R.collect(M.ReducibleMap, N.InitializableNumberSum); +Deno.test("Map fold", () => { + const collect = R.collect(M.FoldableMap, N.InitializableNumberSum); assertEquals(collect(M.readonlyMap()), 0); assertEquals(collect(M.readonlyMap([1, 1], [2, 2], [3, 3])), 6); }); diff --git a/testing/option.test.ts b/testing/option.test.ts index fd0d0ed..c023c57 100644 --- a/testing/option.test.ts +++ b/testing/option.test.ts @@ -108,10 +108,10 @@ Deno.test("Option flatmap", () => { assertEquals(pipe(O.none, O.flatmap(fati)), O.none); }); -Deno.test("Option reduce", () => { - const reduce = O.reduce((n: number, o: number) => n + o, 0); - assertEquals(reduce(O.some(1)), 1); - assertEquals(reduce(O.none), 0); +Deno.test("Option fold", () => { + const fold = O.fold((n: number, o: number) => n + o, 0); + assertEquals(fold(O.some(1)), 1); + assertEquals(fold(O.none), 0); }); Deno.test("Option traverse", () => { diff --git a/testing/pair.test.ts b/testing/pair.test.ts index 2d9aeaf..1342211 100644 --- a/testing/pair.test.ts +++ b/testing/pair.test.ts @@ -71,9 +71,9 @@ Deno.test("Pair unwrap", () => { assertEquals(P.unwrap(P.pair(1, 2)), 1); }); -Deno.test("Pair reduce", () => { +Deno.test("Pair fold", () => { assertEquals( - pipe(P.pair(10, 20), P.reduce(Math.max, Number.NEGATIVE_INFINITY)), + pipe(P.pair(10, 20), P.fold(Math.max, Number.NEGATIVE_INFINITY)), 20, ); }); @@ -99,12 +99,12 @@ Deno.test("Pair BimappablePair", () => { assertStrictEquals(P.BimappablePair.mapSecond, P.mapSecond); }); -Deno.test("Pair ReduciblePair", () => { - assertStrictEquals(P.ReduciblePair.reduce, P.reduce); +Deno.test("Pair FoldablePair", () => { + assertStrictEquals(P.FoldablePair.fold, P.fold); }); Deno.test("Pair TraversablePair", () => { - assertStrictEquals(P.TraversablePair.reduce, P.reduce); + assertStrictEquals(P.TraversablePair.fold, P.fold); assertStrictEquals(P.TraversablePair.traverse, P.traverse); assertStrictEquals(P.TraversablePair.map, P.map); }); diff --git a/testing/record.test.ts b/testing/record.test.ts index 3f0cdf5..78fedd7 100644 --- a/testing/record.test.ts +++ b/testing/record.test.ts @@ -68,18 +68,18 @@ Deno.test("Record map", () => { assertEquals(indexedMap({ a: 0, b: 2 }), { a: 1, b: 3 }); }); -Deno.test("Record reduce", () => { +Deno.test("Record fold", () => { assertEquals( - pipe({ a: 1, b: 2 }, R.reduce((a: number, b: number) => a + b, 0)), + pipe({ a: 1, b: 2 }, R.fold((a: number, b: number) => a + b, 0)), 3, ); - assertEquals(pipe({}, R.reduce(add, 0)), 0); + assertEquals(pipe({}, R.fold(add, 0)), 0); - const reduce = R.reduce((a: number, c: number) => a + c, 0); - assertEquals(reduce({}), 0); - assertEquals(reduce({ a: 1, b: 2 }), 3); + const fold = R.fold((a: number, c: number) => a + c, 0); + assertEquals(fold({}), 0); + assertEquals(fold({ a: 1, b: 2 }), 3); - const indexedReduce = R.reduce( + const indexedReduce = R.fold( (o: string[], a: number, i: string) => a === 0 ? [...o, i] : [...o, a.toString()], [], @@ -263,7 +263,7 @@ Deno.test("Record FunctoRecord", () => { Deno.test("Record TraversableRecord", () => { assertStrictEquals(R.TraversableRecord.map, R.map); - assertStrictEquals(R.TraversableRecord.reduce, R.reduce); + assertStrictEquals(R.TraversableRecord.fold, R.fold); assertStrictEquals(R.TraversableRecord.traverse, R.traverse); }); diff --git a/testing/set.test.ts b/testing/set.test.ts index 365184d..b326e7f 100644 --- a/testing/set.test.ts +++ b/testing/set.test.ts @@ -130,10 +130,10 @@ Deno.test("Set partitionMap", () => { assertEquals(partitionMap(set), [S.set(2, 3), S.set(1)]); }); -Deno.test("Set reduce", () => { - const reduce = S.reduce((n: number, o: number) => n + o, 0); - assertEquals(reduce(S.init()), 0); - assertEquals(reduce(S.set(1, 2, 3)), 6); +Deno.test("Set fold", () => { + const fold = S.fold((n: number, o: number) => n + o, 0); + assertEquals(fold(S.init()), 0); + assertEquals(fold(S.set(1, 2, 3)), 6); }); Deno.test("Set traverse", () => { @@ -170,7 +170,7 @@ Deno.test("Set FilterableSet", () => { Deno.test("Set TraversableSet", () => { assertStrictEquals(S.TraversableSet.map, S.map); - assertStrictEquals(S.TraversableSet.reduce, S.reduce); + assertStrictEquals(S.TraversableSet.fold, S.fold); assertStrictEquals(S.TraversableSet.traverse, S.traverse); }); diff --git a/testing/sync.test.ts b/testing/sync.test.ts index 052b41f..a0a51d6 100644 --- a/testing/sync.test.ts +++ b/testing/sync.test.ts @@ -28,9 +28,9 @@ Deno.test("Sync flatmap", () => { assertEqualsSync(flatmap(S.wrap(1)), S.wrap(2)); }); -Deno.test("Sync reduce", () => { - const reduce = S.reduce((acc: number, cur: number) => acc + cur, 0); - assertEquals(reduce(S.wrap(1)), 1); +Deno.test("Sync fold", () => { + const fold = S.fold((acc: number, cur: number) => acc + cur, 0); + assertEquals(fold(S.wrap(1)), 1); }); Deno.test("Sync traverse", () => { diff --git a/testing/sync_either.test.ts b/testing/sync_either.test.ts index fe90639..fd5737d 100644 --- a/testing/sync_either.test.ts +++ b/testing/sync_either.test.ts @@ -74,11 +74,11 @@ Deno.test("SyncEither mapSecond", () => { assertEqualsIO(mapSecond(SE.right(0)), SE.right(0)); }); -Deno.test("SyncEither reduce", () => { - const reduce = SE.reduce((a: number, c: number) => a + c, 0); +Deno.test("SyncEither fold", () => { + const fold = SE.fold((a: number, c: number) => a + c, 0); - assertEquals(reduce(SE.left(-1)), 0); - assertEquals(reduce(SE.right(1)), 1); + assertEquals(fold(SE.left(-1)), 0); + assertEquals(fold(SE.right(1)), 1); }); Deno.test("SyncEither alt", () => { diff --git a/testing/these.test.ts b/testing/these.test.ts index 7a4c022..ee6963c 100644 --- a/testing/these.test.ts +++ b/testing/these.test.ts @@ -67,11 +67,11 @@ Deno.test("These map", () => { assertEquals(map(T.both(1, 1)), T.both(1, 2)); }); -Deno.test("These reduce", () => { - const reduce = T.reduce((n: number, m: number) => n + m, 0); - assertEquals(reduce(T.left(1)), 0); - assertEquals(reduce(T.right(1)), 1); - assertEquals(reduce(T.both(1, 1)), 1); +Deno.test("These fold", () => { + const fold = T.fold((n: number, m: number) => n + m, 0); + assertEquals(fold(T.left(1)), 0); + assertEquals(fold(T.right(1)), 1); + assertEquals(fold(T.both(1, 1)), 1); }); Deno.test("These traverse", () => { diff --git a/testing/tree.test.ts b/testing/tree.test.ts index 1b933d4..7a031f0 100644 --- a/testing/tree.test.ts +++ b/testing/tree.test.ts @@ -56,10 +56,10 @@ Deno.test("Tree flatmap", () => { assertEquals(flatmap(T.wrap(0)), T.wrap(0)); }); -Deno.test("Tree reduce", () => { - const reduce = T.reduce((n: number, i: number) => n + i, 0); - assertEquals(reduce(T.wrap(1)), 1); - assertEquals(reduce(T.wrap(1, [T.wrap(2)])), 3); +Deno.test("Tree fold", () => { + const fold = T.fold((n: number, i: number) => n + i, 0); + assertEquals(fold(T.wrap(1)), 1); + assertEquals(fold(T.wrap(1, [T.wrap(2)])), 3); }); Deno.test("Tree traverse", () => { diff --git a/these.ts b/these.ts index 4392e74..f0e44eb 100644 --- a/these.ts +++ b/these.ts @@ -4,7 +4,7 @@ import type { Bimappable } from "./bimappable.ts"; import type { Combinable } from "./combinable.ts"; import type { Flatmappable } from "./flatmappable.ts"; import type { Mappable } from "./mappable.ts"; -import type { Reducible } from "./reducible.ts"; +import type { Foldable } from "./foldable.ts"; import type { Showable } from "./showable.ts"; import type { Traversable } from "./traversable.ts"; @@ -88,7 +88,7 @@ export function mapSecond( ); } -export function reduce( +export function fold( foao: (o: O, a: A) => O, o: O, ): (ta: These) => O { @@ -112,11 +112,11 @@ export const BimappableThese: Bimappable = { map, mapSecond }; export const MappableThese: Mappable = { map }; -export const ReducibleThese: Reducible = { reduce }; +export const FoldableThese: Foldable = { fold }; export const TraversableThese: Traversable = { map, - reduce, + fold, traverse, }; diff --git a/traversable.ts b/traversable.ts index de00cf9..5e8752a 100644 --- a/traversable.ts +++ b/traversable.ts @@ -4,23 +4,23 @@ * turning an Array> into Option> or as complicated * as creating all combinations of numbers in three Array. * - * @module Mappable + * @module Traversable * @since 2.0.0 */ import type { $, Hold, Kind } from "./kind.ts"; import type { Applicable } from "./applicable.ts"; import type { Mappable } from "./mappable.ts"; -import type { Reducible } from "./reducible.ts"; +import type { Foldable } from "./foldable.ts"; /** - * A Traversable structure extends Mappable and Reducible. It contains the - * methods map, reduce, and traverse. + * A Traversable structure extends Mappable and Foldable. It contains the + * methods map, fold, and traverse. * * @since 2.0.0 */ export interface Traversable - extends Mappable, Reducible, Hold { + extends Mappable, Foldable, Hold { readonly traverse: ( A: Applicable, ) => ( diff --git a/tree.ts b/tree.ts index 5807feb..6ea7099 100644 --- a/tree.ts +++ b/tree.ts @@ -135,16 +135,16 @@ export function apply(ua: Tree): (tfai: Tree<(a: A) => I>) => Tree { } /** - * The reduce function for Reducible. + * The fold function for Foldable. * * @since 2.0.0 */ -export function reduce( +export function fold( foao: (o: O, a: A) => O, o: O, ): (ta: Tree) => O { - const reducer = (result: O, tree: Tree) => reduce(foao, result)(tree); - return (ta) => TraversableArray.reduce(reducer, foao(o, ta.value))(ta.forest); + const foldr = (result: O, tree: Tree) => fold(foao, result)(tree); + return (ta) => TraversableArray.fold(foldr, foao(o, ta.value))(ta.forest); } /** @@ -270,7 +270,7 @@ export const MappableTree: Mappable = { map }; /** * @since 2.0.0 */ -export const TraversableTree: Traversable = { map, reduce, traverse }; +export const TraversableTree: Traversable = { map, fold, traverse }; /** * @since 2.0.0