import type * as P from "@principia/prelude"; import * as HKT from "@principia/prelude/HKT"; import { flow } from "../Function"; import { Functor, map, map_ } from "./functor"; import type { URI, V } from "./model"; import { chain_ } from "./monad"; /* * ------------------------------------------- * Apply Array * ------------------------------------------- */ /** * ```haskell * ap_ :: Apply f => (f (a -> b), f a) -> f b * ``` * * Apply a function to an argument under a type constructor * * @category Apply * @since 1.0.0 */ export const ap_ = (fab: ReadonlyArray<(a: A) => B>, fa: ReadonlyArray): ReadonlyArray => chain_(fab, (f) => map_(fa, f)); /** * ```haskell * ap :: Apply f => f a -> f (a -> b) -> f b * ``` * * Apply a function to an argument under a type constructor * * @category Apply * @since 1.0.0 */ export const ap = (fa: ReadonlyArray) => (fab: ReadonlyArray<(a: A) => B>): ReadonlyArray => ap_(fab, fa); /** * ```haskell * apFirst_ :: Apply f => (f a, f b) -> f a * ``` * * Combine two effectful actions, keeping only the result of the first * * @category Apply * @since 1.0.0 */ export const apFirst_ = (fa: ReadonlyArray, fb: ReadonlyArray): ReadonlyArray => ap_( map_(fa, (a) => () => a), fb ); /** * ```haskell * apFirst :: Apply f => f b -> f a -> f a * ``` * * Combine two effectful actions, keeping only the result of the first * * @category Apply * @since 1.0.0 */ export const apFirst: (fb: ReadonlyArray) => (fa: ReadonlyArray) => ReadonlyArray = (fb) => flow( map((a) => () => a), ap(fb) ); /** * ```haskell * apSecond_ :: Apply f => (f a, f b) -> f b * ``` * * Combine two effectful actions, keeping only the result of the second * * @category Apply * @since 1.0.0 */ export const apSecond_ = (fa: ReadonlyArray, fb: ReadonlyArray): ReadonlyArray => ap_( map_(fa, () => (b: B) => b), fb ); /** * ```haskell * apSecond :: Apply f => f b -> f a -> f b * ``` * * Combine two effectful actions, keeping only the result of the second * * @category Apply * @since 1.0.0 */ export const apSecond = (fb: ReadonlyArray): ((fa: ReadonlyArray) => ReadonlyArray) => flow( map(() => (b: B) => b), ap(fb) ); export const zipWith_ = ( fa: ReadonlyArray, fb: ReadonlyArray, f: (a: A, b: B) => C ): ReadonlyArray => { const fc = []; const len = Math.min(fa.length, fb.length); for (let i = 0; i < len; i++) { fc[i] = f(fa[i], fb[i]); } return fc; }; export const mapBoth_ = zipWith_; export const zipWith = (fb: ReadonlyArray, f: (a: A, b: B) => C) => ( fa: ReadonlyArray ): ReadonlyArray => zipWith_(fa, fb, f); export const mapBoth = zipWith; export const Apply: P.Apply<[URI], V> = HKT.instance({ ...Functor, ap, ap_, mapBoth: zipWith, mapBoth_: zipWith_ });