import { Functor } from '../data/Functor'; export interface ChainFunction { (a: A): Monad } /** * Monad */ export interface Monad extends Functor { of(t: A): Monad; chain(f: (a: A) => Monad): Monad; } /** * composeK two monadic functions into one. */ export const composeK = (f: ChainFunction, g: ChainFunction): ChainFunction => x => g(x).chain(f); /** * pipeK the result of one monadic function into another. */ export const pipeK = (f: ChainFunction, g: ChainFunction): ChainFunction => (x: A) => (f(x) as Monad).chain(g); /** * chain is a partially applied version of a Monad's chain. * It allows us to avoid anonymous functions when chaining monads. */ export const chain = (f: ChainFunction) => (m: Monad) => m.chain(f);