// https://github.com/fantasyland/fantasy-land#setoid interface Setoid { equals(other: A): boolean; 'fantasy-land/equals'?(other: A): boolean; } /* The (covariant) functor typeclass */ // https://github.com/fantasyland/fantasy-land#functor interface Functor { map(fn: (val: T) => V): Functor; 'fantasy-land/map'?(fn: (val: T) => V): Functor; } /* Applicative allows applying wrapped functions to wrapped elements */ // https://github.com/fantasyland/fantasy-land#applicative interface Applicative { ap(afn: Applicative<(val: T) => V>): Applicative 'fantasy-land/ap'?(afn: Applicative<(val: T) => V>): Applicative } // https://github.com/fantasyland/fantasy-land#chain interface Chain { chain(fn: (val: T) => Chain): Chain; 'fantasy-land/chain'?(fn: (val: T) => Chain): Chain; } /* Typeclass for binding, the core monadic transformation */ interface Bind extends Chain { bind(fn: (val: T) => Bind): Bind // alias of chain chain(fn: (val: T) => Bind): Bind; flatMap(fn: (val: T) => Bind): Bind // alias of chain join(): Bind // works only if T = Bind } /* Typeclass for catamorphism */ interface Catamorphism { cata(l: (e?: F) => C, r: (v: T) => C): C; } /* Typeclass for traversables */ export interface ITraversable { foldLeft(initial: V): (fn: (acc: V, val: T) => V) => V; foldRight(initial: V): (fn: (val: T, acc: V) => V) => V; } /**************************************************************** * Basic Monad Interface */ interface IMonad extends Functor, Bind, Applicative { /* These all are defined in Functor, Bind and Applicative: */ bind(fn: (val: T) => IMonad): IMonad; flatMap(fn: (val: T) => IMonad): IMonad; chain(fn: (val: T) => IMonad): IMonad; map(fn: (val: T) => V): IMonad; join(): IMonad; // only if T = IMonad /* These are monet-Monad-specific: */ takeLeft(m: IMonad): IMonad; takeRight(m: IMonad): IMonad; ['@@type']: string; } interface IMonadFactory extends Function { (val: T): IMonad; } interface IMonadStatic { unit: IMonadFactory; of: IMonadFactory; // alias for unit pure: IMonadFactory; // alias for unit } /**************************************************************** * Identity */ export interface Identity extends IMonad, Setoid>, Iterable { /* Inherited from Monad: */ bind(fn: (val: T) => Identity): Identity; flatMap(fn: (val: T) => Identity): Identity; chain(fn: (val: T) => Identity): Identity; map(fn: (val: T) => V): Identity; join(): Identity; // if T is Identity takeLeft(m: Identity): Identity; takeRight(m: Identity): Identity; /* Inherited from Applicative */ ap(applyFn: Identity<(val: T) => V>): Identity; /* Identity specific */ contains(val: T): boolean; every(fn: (e: T) => boolean): boolean; forall(fn: (e: T) => boolean): boolean; exists(fn: (e: T) => boolean): boolean; forEach(fn: (val: T) => void): void; get(): T; toArray(): Array; toSet(): Set; toList(): List; to>(ctor: (iter: Iterable) => I): I; } interface IIdentityFactory extends IMonadFactory { (value: V): Identity; } interface IIdentityStatic extends IIdentityFactory, IMonadStatic { unit: IIdentityFactory; of: IIdentityFactory; // alias for unit pure: IIdentityFactory; // alias for unit isOfType(target: any): boolean; isInstance(target: any): target is Identity; } export const Identity: IIdentityStatic; /**************************************************************** * Maybe */ export interface Maybe> extends Setoid>, ITraversable, Catamorphism, Iterable { /* Inherited from Monad: */ bind>(fn: (val: T) => Maybe): Maybe; flatMap>(fn: (val: T) => Maybe): Maybe; chain>(fn: (val: T) => Maybe): Maybe; map>(fn: (val: T) => V): Maybe; join(): T extends Maybe ? V : never; takeLeft(m: Maybe): Maybe; takeRight(m: Maybe): Maybe; /* Inherited from Applicative */ ap>(maybeFn: Maybe<(val: T) => V>): Maybe; /* Maybe specific */ cata(none: () => Z, some: (val: T) => Z): Z; fold(val: V): (fn: (val: T) => V) => V; catchMap(fn: () => Maybe): Maybe; filter(fn: (val: T) => boolean): Maybe; filterNot(fn: (val: T) => boolean): Maybe; isSome(): boolean; isJust(): boolean; isNone(): boolean; isNothing(): boolean; some(): T; just(): T; orSome(val: T): T; orJust(val: T): T; getOrElse(val: T): T; orLazy(fn: () => T|null|undefined): T orNull(): T|null; orUndefined(): T|undefined; orElse(maybe: Maybe): Maybe; orNoneIf(val: boolean): Maybe; orNothingIf(val: boolean): Maybe; contains(val: T): boolean; every(fn: (e: T) => boolean): boolean; forall(fn: (e: T) => boolean): boolean; exists(fn: (e: T) => boolean): boolean; forEach(fn: (val: T) => void): void; orElseRun(fn: () => void): void; toArray(): Array; toSet(): Set; toList(): List; toEither(left?: E): Either; toValidation(fail?: E): Validation; to>(ctor: (iter: Iterable) => I): I; } interface ISomeStatic extends IMonadFactory { (value: V): Maybe; } interface INoneStatic extends IMonadFactory { (): Maybe; } interface IMaybeStatic extends IMonadStatic { Some: ISomeStatic; some: ISomeStatic; Just: ISomeStatic; None: INoneStatic; none: INoneStatic; Nothing: INoneStatic; fromFalsy(val: V|null|undefined): Maybe; fromNull(val: V|null|undefined): Maybe; fromUndefined(val: V|undefined): Maybe; unit: ISomeStatic; of: ISomeStatic; // alias for unit pure: ISomeStatic; // alias for unit isOfType(target: any): boolean; isInstance(target: any): target is Maybe; } export const Some: ISomeStatic; export const Just: ISomeStatic; export const None: INoneStatic; export const Nothing: INoneStatic; export const Maybe: IMaybeStatic; /**************************************************************** * Either */ export interface Either extends IMonad, Setoid>, ITraversable, Catamorphism { /* Inherited from Monad: */ bind(fn: (val: T) => Either): Either; flatMap(fn: (val: T) => Either): Either; chain(fn: (val: T) => Either): Either; map(fn: (val: T) => V): Either; join(): Either; // if T is Either takeLeft(m: Either): Either; takeRight(m: Either): Either; /* Inherited from Applicative */ ap(eitherFn: Either V>): Either; /* Either specific */ cata(leftFn: (err: E) => Z, rightFn: (val: T) => Z): Z; fold(leftFn: (err: E) => Z, rightFn: (val: T) => Z): Z; catchMap(fn: (err: E) => Either): Either; swap(): Either; bimap(leftFn: (err: E) => Z, rightFn: (val: T) => V): Either; leftMap(fn: (leftVal: E) => F): Either; isRight(): boolean; isLeft(): boolean; right(): T; left(): E; forEach(fn: (val: T) => void): void; forEachLeft(fn: (val: E) => void): void; toValidation(): Validation; toMaybe(): Maybe; } interface IEitherStatic extends IMonadStatic { Right: IRightStatic; right: IRightStatic; Left: ILeftStatic; left: ILeftStatic; unit: IRightStatic; of: IRightStatic; // alias for unit pure: IRightStatic; // alias for unit isOfType(target: any): boolean; isInstance(target: any): target is Either; } interface IRightStatic extends IMonadFactory { (val: V): Either; } interface ILeftStatic extends IMonadFactory { (val: F): Either; } export const Either: IEitherStatic; export const Right: IRightStatic; export const Left: ILeftStatic; /**************************************************************** * Validation */ interface IValidationAcc extends Function { (): IValidationAcc; } export interface Validation extends IMonad, Setoid>, ITraversable, Catamorphism { /* Inherited from Monad: */ bind(fn: (val: T) => Validation): Validation; flatMap(fn: (val: T) => Validation): Validation; chain(fn: (val: T) => Validation): Validation; map(fn: (val: T) => V): Validation; join(): Validation; // if T is Validation takeLeft(m: Validation): Validation; takeRight(m: Validation): Validation; /* Inherited from Applicative */ ap(eitherFn: Validation V>): Validation; /* Validation specific */ cata(failFn: (fail: E) => Z, successFn: (val: T) => Z): Z; fold(failFn: (fail: E) => Z, successFn: (val: T) => Z): Z; catchMap(fn: (fail: E) => Validation): Validation; swap(): Validation; bimap(fnF: (fail: E) => F, fnS: (val: T) => V): Validation; failMap(fn: (fail: E) => F): Validation; isSuccess(): boolean; isFail(): boolean; success(): T; fail(): E; forEach(fn: (val: T) => void): void; forEachFail(fn: (val: E) => void): void; acc(): Validation; toEither(): Either; toMaybe(): Maybe; } interface IValidationStatic extends IMonadStatic { Success: ISuccessStatic; Fail: IFailStatic; success: ISuccessStatic; fail: IFailStatic; unit: ISuccessStatic; of: ISuccessStatic; // alias for unit pure: ISuccessStatic; // alias for unit point: ISuccessStatic; // alias for unit isOfType(target: any): boolean; isInstance(target: any): target is Validation; } interface ISuccessStatic extends IMonadFactory { (val: T): Validation; } interface IFailStatic extends IMonadFactory { (err: E): Validation; } export const Validation: IValidationStatic; export const Success: ISuccessStatic; export const Fail: IFailStatic; /**************************************************************** * List */ export interface List extends IMonad, Setoid>, ITraversable, Iterable { /* Inherited from Monad: */ bind(fn: (val: T) => List): List; flatMap(fn: (val: T) => List): List; chain(fn: (val: T) => List): List; map(fn: (val: T) => V): List; join(): List; // if T is List takeLeft(m: List): List; takeRight(m: List): List; /* Inherited from Applicative */ ap(listFn: List<(val: T) => V>): List; /* List specific */ filter(fn: (val: T) => boolean): List; filterNot(fn: (val: T) => boolean): List; find(fn: (val: T) => boolean): Maybe>; cons(a: T): List; snoc(a: T): List; isNEL(): boolean; size(): number; head(): T | undefined; headMaybe(): Maybe>; append(list: List): List; concat(list: List): List; reverse(): List; tail(): List; tails(): List>; flatten(): List; flattenMaybe(): T extends Maybe ? List : never; contains(val: T): boolean; every(fn: (e: T) => boolean): boolean; forall(fn: (e: T) => boolean): boolean; exists(fn: (e: T) => boolean): boolean; forEach(fn: (val: T) => void): void; sequence(m: IMaybeStatic): Maybe>; sequence(m: IEitherStatic): Either>; sequence(m: IValidationStatic): Validation, List>; sequence(m: IIOStatic): IO>; sequence(m: IReaderStatic): Reader>; sequenceMaybe(): Maybe>; sequenceEither(): Either>; sequenceValidation(): Validation, List>; sequenceIO(): IO>; sequenceReader(): Reader>; toArray(): Array; toSet(): Set; to>(ctor: (iter: Iterable) => I): I; } export interface Nil extends List { cons(a: T): List; append(list: List): List; concat(list: List): List; } interface IListFactory extends IMonadFactory { (val: T): List; } interface IListStatic extends IMonadStatic { (): List; (val: T, tail?: List): List; fromArray(arr: T[]): List; from(iter: Iterable): List; unit: IListFactory; of: IListFactory; // alias for unit pure: IListFactory; // alias for unit isOfType(target: any): boolean; isInstance(target: any): target is List; } export const List: IListStatic; export const Nil: Nil; /**************************************************************** * NEL */ export interface NEL extends IMonad, Setoid>, ITraversable, Iterable { /* Inherited from Monad: */ bind(fn: (val: T) => NEL): NEL; flatMap(fn: (val: T) => NEL): NEL; chain(fn: (val: T) => NEL): NEL; map(fn: (val: T) => V): NEL; join(): NEL; // if T is NEL | List takeLeft(m: NEL): NEL; takeRight(m: NEL): NEL; /* from CoMonad: */ mapTails(fn: (val: NEL) => V): NEL; cobind(fn: (val: NEL) => V): NEL; // alias for mapTails coflatMap(fn: (val: NEL) => V): NEL; // alias for mapTails cojoin(): NEL>; // alias for tails copure(): T; // alias for head extract(): T; // alias for head /* Inherited from Applicative */ ap(listFn: NEL<(val: T) => V>): NEL; /* NEL specific */ reduceLeft(fn: (acc: T, element: T) => T): T; filter(fn: (val: T) => boolean): List; filterNot(fn: (val: T) => boolean): List; find(fn: (val: T) => boolean): Maybe; cons(a: T): NEL; snoc(a: T): NEL; isNEL(): boolean; size(): number; head(): T; append(list: NEL): NEL; concat(list: NEL): NEL; reverse(): NEL; tail(): List; tails(): NEL>; contains(val: T): boolean; every(fn: (e: T) => boolean): boolean; forall(fn: (e: T) => boolean): boolean; exists(fn: (e: T) => boolean): boolean; forEach(fn: (val: T) => void): void; flatten(): T extends List | NEL ? List : never; flattenMaybe(): T extends Maybe ? List : never; toArray(): Array; toList(): List; toSet(): Set; to>(ctor: (iter: Iterable) => I): I; } export type NonEmptyList = NEL; interface INELFactory extends IMonadFactory { (val: T, tail?: List): NEL; } interface INELStatic extends INELFactory, IMonadStatic { fromList(arr: List): Maybe>; fromArray(arr: T[]): Maybe>; from(iter: Iterable): Maybe>; unit: INELFactory; of: INELFactory; // alias for unit pure: INELFactory; // alias for unit isOfType(target: any): boolean; isInstance(target: any): target is NEL; } export const NonEmptyList: INELStatic; export const NEL: INELStatic; /**************************************************************** * IO */ export interface IO extends IMonad { /* Inherited from Monad: */ bind(fn: (val: T) => IO): IO; flatMap(fn: (val: T) => IO): IO; chain(fn: (val: T) => IO): IO; map(fn: (v: T) => V): IO; join(): IO; // if T is IO takeLeft(m: IO): IO; takeRight(m: IO): IO; /* Inherited from Applicative: */ ap(ioFn: IO<(v: T) => V>): IO; /* IO specific: */ run(): T; perform(): T; // Alias for run() performUnsafeIO(): T; // Alias for run() } interface IIOFactory extends IMonadFactory { (fn: () => T): IO; } interface IIOStatic extends IIOFactory, IMonadStatic { unit: IIOFactory; of: IIOFactory; // alias for unit pure: IIOFactory; // alias for unit io: IIOFactory; // alias for unit isOfType(target: any): boolean; isInstance(target: any): target is IO; } export const IO: IIOStatic; /**************************************************************** * Reader */ export interface Reader extends IMonad { /* Inherited from Monad: */ bind(fn: (val: A) => Reader): Reader; flatMap(fn: (val: A) => Reader): Reader; chain(fn: (val: A) => Reader): Reader; map(fn: (val: A) => B): Reader; join(): Reader; // if A is Reader takeLeft(m: Reader): Reader; takeRight(m: Reader): Reader; ap(rfn: Reader B>): Reader; /* Reader-specific: */ run(config: E): A; local(fn: (val: X) => E): Reader; } interface IReaderFactory extends IMonadFactory { (fn: (env: E) => A): Reader; } interface IReaderStatic extends IReaderFactory, IMonadStatic { unit: IReaderFactory; of: IReaderFactory; // alias for unit pure: IReaderFactory; // alias for unit point: IReaderFactory; // alias for unit ask(): Reader; isOfType(target: any): boolean; isInstance(target: any): target is Reader; } export const Reader: IReaderStatic; /**************************************************************** * Free */ export interface Free extends IMonad { /* A free monad over functor F. * It holds values of type F for some functor F. * * * Typing caveats: * TypeScript does not support higher-kinded types, meaning you can't * just specify the type of the functor. This leads to the following issues: * * 1. Some methods operating on type T require FT or FFT as type parameters. * FT = F and FFT = F>, but we can't simply infer that. * 2. The Free interface does not include the information on what kind * of functor is used. So it is possible to `bind` two free monads * over different functors. This will most likely crash, and we can't * statically prohibit it. As a general rule, free monads over different * functors are totally incompatible. */ bind(fn: (val: A) => Free): Free; flatMap(fn: (val: A) => Free): Free; chain(fn: (val: A) => Free): Free; join(): Free; // only if A = Free on the same functor map(fn: (val: A) => V): Free; takeLeft(other: Free): Free; takeRight(other: Free): Free; /* Free-specific: */ // evaluates a single layer resume(): Either; // runs to completion using given extraction function: go(extract: (sus: FFA) => Free): A; } interface IFreeStatic extends IMonadStatic { Return: IReturnStatic; Suspend: ISuspendStatic; unit: IReturnStatic; of: IReturnStatic; // alias for unit pure: IReturnStatic; // alias for unit liftF(fa: FA): Free; // FA = F isOfType(target: any): boolean; isInstance(target: any): target is Free; } interface IReturnStatic extends IMonadFactory { (a: A): Free; } interface ISuspendStatic extends IMonadFactory { (ffa: FFA): Free; } export const Free: IFreeStatic; export const Return: IReturnStatic; export const Suspend: ISuspendStatic;