UNPKG

rivo

Version:

🤖 The ultimate library you need for composable type-level programming in TypeScript, powered by HKT.

97 lines (87 loc) 2.75 kB
import type ChainFn from "./Chain"; import type FlattenFn from "./Flatten"; import type { Fn1, PartialApply } from "../../HKT"; import type { ValueOf } from "../../Obj/ValueOf"; import type { Eq, Lazied, Lazied$Get } from "../../helpers"; import type { Applicative } from "../Applicative"; import type { HKT, Kind } from "../HKT"; /** * A type class for types that can be converted to a string. */ export type Monad<T = unknown> = Lazied$Get<MonadL<T>>; /** * {@link Lazied} version of {@link Monad}. */ export type MonadL<T = unknown> = Lazied<Kind<MonadImpl[keyof MonadImpl][0], T>>; /** * Type class constraints for type class {@link Monad}. */ export interface TypeClass$$Monad<F extends Applicative> { /** * Flatten a nested structure of a {@link Monad}. * * **⚠️ Warning:** Correctness of the method is not fully checked, so be careful when implementing * this method. * * Sig: `<F<~>, T>(f: F<F<T>>) => F<T>` */ Flatten: Fn1<Kind<F, F>, F>; } /** * Implementations for type class {@link Monad}. */ export interface MonadImpl {} /** * Helper type for implementing type class {@link Monad}. */ export type ImplMonadFor<F extends Applicative, TypeClass extends TypeClass$$Monad<F>> = [ F, TypeClass, ]; /** * Get the matching entry of {@link MonadImpl} for `F`. * @private */ type _Monad$GetMatch<F extends Monad> = ValueOf<{ [P in keyof MonadImpl as F extends MonadImpl[P][0] ? P : never]: MonadImpl[P]; }>; /** * Get the constructor of `F` from {@link MonadImpl}. */ export type Monad$GetConstruct<F extends Monad> = Eq<F, Monad> extends true ? Monad : _Monad$GetMatch<F> extends [infer F extends HKT, unknown] ? F : never; /** * The **unsafe** version of {@link Monad$GetConstruct} (i.e. no type checking with `F`). */ export type Monad$GetConstructW<F> = F extends Monad ? Monad$GetConstruct<F> : never; /** * Get the type class of `F` from {@link MonadImpl}. */ export type Monad$GetTypeClass<F extends Monad> = _Monad$GetMatch<F> extends [unknown, infer TypeClass] ? TypeClass : never; /** * The **unsafe** version of {@link Monad$GetTypeClass} (i.e. no type checking with `F`). */ export type Monad$GetTypeClassW<F> = F extends Monad ? Monad$GetTypeClass<F> : never; /*********** * Methods * ***********/ /** * Methods for `Monad`. */ export namespace Monad { /** * [Fn] Flatten a {@link Monad} of a {@link Monad} into a {@link Monad}. * * Sig: `<F<~>, T>(f: F<F<T>>) => F<T>` */ export type Flatten = FlattenFn; /** * [Fn] Map a function over a {@link Monad} and flatten the result. * * Sig: `<F<~>, T, U>[f: (x: T) => F<U>](fa: F<T>) => F<U>` */ export type Chain<F extends Fn1<never, Monad>> = PartialApply<ChainFn, [F]>; }