import type * as P from "@principia/prelude"; import * as HKT from "@principia/prelude/HKT"; import type { Monoid } from "@principia/prelude/Monoid"; import type { URI, V } from "./model"; /* * ------------------------------------------- * Foldable Array * ------------------------------------------- */ /** * ```haskell * reduceWithIndex_ :: (FoldableWithIndex t, Index k) => * (t a, b, ((k, b, a) -> b)) -> b * ``` * * @category FoldableWithIndex * @since 1.0.0 */ export const reduceWithIndex_ = (fa: ReadonlyArray, b: B, f: (i: number, b: B, a: A) => B): B => { const len = fa.length; let r = b; for (let i = 0; i < len; i++) { r = f(i, r, fa[i]); } return r; }; /** * ```haskell * reduceWithIndex :: (FoldableWithIndex t, Index k) => * (b, ((k, b, a) -> b)) -> t a -> b * ``` * * @category FoldableWithIndex * @since 1.0.0 */ export const reduceWithIndex = (b: B, f: (i: number, b: B, a: A) => B) => (fa: ReadonlyArray): B => reduceWithIndex_(fa, b, f); /** * ```haskell * reduce_ :: Foldable t => (t a, b, ((b, a) -> b)) -> b * ``` * * @category Foldable * @since 1.0.0 */ export const reduce_ = (fa: ReadonlyArray, b: B, f: (b: B, a: A) => B): B => reduceWithIndex_(fa, b, (_, b, a) => f(b, a)); /** * ```haskell * reduce :: Foldable t => (b, ((b, a) -> b)) -> t a -> b * ``` * * @category Foldable * @since 1.0.0 */ export const reduce = (b: B, f: (b: B, a: A) => B) => (fa: ReadonlyArray): B => reduceWithIndex_(fa, b, (_, b, a) => f(b, a)); /** * ```haskell * reduceRightWithIndex_ :: (FoldableWithIndex t, Index k) => * (t a, b, ((k, a, b) -> b)) -> b * ``` * * @category FoldableWithIndex * @since 1.0.0 */ export const reduceRightWithIndex_ = (fa: ReadonlyArray, b: B, f: (i: number, a: A, b: B) => B): B => { let r = b; for (let i = fa.length - 1; i >= 0; i--) { r = f(i, fa[i], r); } return r; }; /** * ```haskell * reduceRightWithIndex :: (FoldableWithIndex t, Index k) => * (b, ((k, a, b) -> b)) -> t a -> b * ``` * * @category FoldableWithIndex * @since 1.0.0 */ export const reduceRightWithIndex = (b: B, f: (i: number, a: A, b: B) => B) => (fa: ReadonlyArray): B => reduceRightWithIndex_(fa, b, f); /** * ```haskell * reduceRight_ :: Foldable t => (t a, b, ((a, b) -> b)) -> b * ``` * * @category Foldable * @since 1.0.0 */ export const reduceRight_ = (fa: ReadonlyArray, b: B, f: (a: A, b: B) => B): B => reduceRightWithIndex_(fa, b, (_, a, b) => f(a, b)); /** * ```haskell * reduceRight :: Foldable t => (b, ((a, b) -> b)) -> t a -> b * ``` * * @category Foldable * @since 1.0.0 */ export const reduceRight = (b: B, f: (a: A, b: B) => B) => (fa: ReadonlyArray): B => reduceRight_(fa, b, f); /** * ```haskell * foldMapWithIndex_ :: (Monoid m, FoldableWithIndex f, Index k) => * m b -> (f a, ((k, a) -> b) -> b * ``` * * @category FoldableWithIndex * @since 1.0.0 */ export const foldMapWithIndex_ = (M: Monoid) => (fa: ReadonlyArray, f: (i: number, a: A) => M): M => reduceWithIndex_(fa, M.nat, (i, b, a) => M.combine_(b, f(i, a))); /** * ```haskell * foldMapWithIndex :: (Monoid m, FoldableWithIndex f, Index k) => * m b -> ((k, a) -> b) -> f a -> b * ``` * * @category FoldableWithIndex * @since 1.0.0 */ export const foldMapWithIndex = (M: Monoid) => (f: (i: number, a: A) => M) => (fa: ReadonlyArray) => foldMapWithIndex_(M)(fa, f); /** * ```haskell * foldMap_ :: (Monoid m, Foldable f) => * m b -> (f a, (a -> b)) -> b * ``` * * @category Foldable * @since 1.0.0 */ export const foldMap_ = (M: Monoid): ((fa: ReadonlyArray, f: (a: A) => M) => M) => { const foldMapWithIndexM_ = foldMapWithIndex_(M); return (fa, f) => foldMapWithIndexM_(fa, (_, a) => f(a)); }; /** * ```haskell * foldMap :: (Monoid m, Foldable f) => m b -> (a -> b) -> f a -> b * ``` * * @category Foldable * @since 1.0.0 */ export const foldMap = (M: Monoid) => (f: (a: A) => M) => (fa: ReadonlyArray): M => foldMap_(M)(fa, f); export const FoldableWithIndex: P.FoldableWithIndex<[URI], V> = HKT.instance({ reduceWithIndex_, reduceWithIndex, reduceRightWithIndex, reduceRightWithIndex_, foldMapWithIndex, foldMapWithIndex_ }); export const Foldable: P.Foldable<[URI], V> = HKT.instance({ reduce_, reduce, reduceRight_, reduceRight, foldMap_, foldMap });