import { Functor } from './functor' import { Cartesian } from './cartesian' import { $, HKT, kind } from '.' export interface Apply extends Cartesian, Functor { ap(fab: $ B>, fa: $): $ } export type ApplyInstances = keyof typeof Apply export namespace Apply { const __name = "Apply" } export function ap(fab: $ B>, fa: $): $ { let instance = Apply[kind(fab)] as Apply let faba = instance.product<(a: A) => B, A>(fab, fa) return instance.map((aba: [(a: A) => B, A]) => aba[0](aba[1]), faba) } export function ap2(fabc: $ C>, fa: $, fb: $): $ { let instance = Apply[kind(fabc)] as Apply return ap( instance.map( (f: (a: A, b: B) => C) => (([a, b]: [A, B]) => f(a, b)) , fabc) , instance.product(fa, fb) ) }