/** * Applicable is a structure that allows a function to be applied inside of the * associated concrete structure. For example, `Option` may hold a value of * `(a: A) => B` inside of it. An Applicable for Option would allow one to * apply the `A` in an `Option` to the function `(a: A) => B` in an * `Option<(a: A) => B>`, resulting in an `Option`. * * @module Applicable * @since 2.0.0 */ import type { $, Hold, Kind } from "./kind.ts"; import type { Combinable } from "./combinable.ts"; import type { Mappable } from "./mappable.ts"; import type { Wrappable } from "./wrappable.ts"; /** * The Applicable interface. This interface includes the methods apply, map, and * wrap. * * @since 2.0.0 */ export interface Applicable< U extends Kind, > extends Mappable, Wrappable, Hold { readonly apply: < A, B = never, C = never, D = unknown, E = unknown, >( ta: $, ) => < I, J = never, K = never, L = unknown, >( tfai: $ I, J, K], [L], [E]>, ) => $; } /** * Create a Combinable instance for an Applicable structure given a Combinable for the inner type. * * @example * ```ts * import * as A from "./applicable.ts"; * import * as O from "./option.ts"; * import * as N from "./number.ts"; * * const combinableOption = A.getApplicableCombinable(O.ApplicableOption)(N.CombinableNumberSum); * * const result = combinableOption.combine(O.some(2))(O.some(3)); // Some(5) * ``` * * @since 2.0.0 */ export function getApplicableCombinable( { apply, map }: Applicable, ): ( combinable: Combinable, ) => Combinable<$> { return ( { combine }: Combinable, ): Combinable<$> => { const _map = map(combine); return { combine: (second) => (first) => apply(first)(_map(second)), }; }; }