import { Either, chain as eitherChain, isLeft, isRight } from '@typed/either' import { List, chain as listChain } from '@typed/list' import { Maybe, isJust, isNothing, chain as maybeChain } from '@typed/maybe' import { curry2 } from '@typed/functions' import { isPromiseLike } from '@typed/logic' /** * Creates a new `Monad` from the value contained in another. * Works with `Maybe`, `Either`, `PromiseLike` and `List` data * structures. * @name chain(f: (value: A) => List, list: List): Array */ export const chain: Chain = curry2(function(f: (value: any) => any, list: any): any { if (isJust(list) || isNothing(list)) return maybeChain(f, list) if (isLeft(list) || isRight(list)) return eitherChain(f, list) if (isPromiseLike(list)) return Promise.resolve(list.then(f)) return listChain(f, list) }) export type Chain = { (f: (value: A, index: number) => List, list: List): Array (f: (value: A) => Maybe, maybe: Maybe): Maybe (f: (value: A) => PromiseLike, promise: PromiseLike): Promise (f: (value: B) => Either, either: Either): Either (f: (value: A, index: number) => List): (list: List) => Array (f: (value: A) => Maybe): (maybe: Maybe) => Maybe (f: (value: A) => PromiseLike): (promise: PromiseLike) => Promise (f: (value: B) => Either): (either: Either) => Either }