/** * Provide is a Typeclass to represent the ability to add/remove requirements from Reader-like * effects such as [Env](./Env.ts.md) or [ReaderStream](./ReaderStream.ts.md). * * @since 0.9.2 */ import { Chain, Chain2, Chain3, Chain4 } from 'fp-ts/Chain' import { FromReader, FromReader2, FromReader3, FromReader4 } from 'fp-ts/FromReader' import { pipe } from 'fp-ts/function' import { HKT2, Kind2, Kind3, Kind4, URIS2, URIS3, URIS4 } from 'fp-ts/HKT' import { ApplyVariance, Hkt } from './HKT' /** * Type-class for providing some or all of the requirements. */ /** * @since 0.9.2 * @category Typeclass */ export interface Provide { readonly provideSome: (provided: A) => (hkt: HKT2) => HKT2 readonly provideAll: (provided: A) => (hkt: HKT2, B>) => HKT2 readonly useSome: Provide['provideSome'] readonly useAll: Provide['provideAll'] } /** * @since 0.9.2 * @category Typeclass */ export interface ProvideSome extends Pick, 'provideSome'> {} /** * @since 0.9.2 * @category Typeclass */ export interface ProvideAll extends Pick, 'provideAll'> {} /** * @since 0.9.2 * @category Typeclass */ export interface UseSome extends Pick, 'useSome'> {} /** * @since 0.9.2 * @category Typeclass */ export interface UseAll extends Pick, 'useAll'> {} /** * @since 0.9.2 * @category Typeclass */ export interface Provide2 { readonly provideSome: (provided: A) => (hkt: Hkt) => Hkt readonly provideAll: (provided: A) => (hkt: Hkt, B]>) => Hkt readonly useSome: Provide2['provideSome'] readonly useAll: Provide2['provideAll'] } /** * @since 0.9.2 * @category Typeclass */ export interface ProvideSome2 extends Pick, 'provideSome'> {} /** * @since 0.9.2 * @category Typeclass */ export interface ProvideAll2 extends Pick, 'provideAll'> {} /** * @since 0.9.2 * @category Typeclass */ export interface UseSome2 extends Pick, 'useSome'> {} /** * @since 0.9.2 * @category Typeclass */ export interface UseAll2 extends Pick, 'useAll'> {} /** * @since 0.9.2 * @category Typeclass */ export interface Provide3 { readonly provideSome: ( provided: A, ) => (hkt: Hkt) => Hkt readonly provideAll: ( provided: A, ) => (hkt: Hkt, E, B]>) => Hkt readonly useSome: Provide3['provideSome'] readonly useAll: Provide3['provideAll'] } /** * @since 0.9.2 * @category Typeclass */ export interface ProvideSome3 extends Pick, 'provideSome'> {} /** * @since 0.9.2 * @category Typeclass */ export interface ProvideAll3 extends Pick, 'provideAll'> {} /** * @since 0.9.2 * @category Typeclass */ export interface UseSome3 extends Pick, 'useSome'> {} /** * @since 0.9.2 * @category Typeclass */ export interface UseAll3 extends Pick, 'useAll'> {} /** * @since 0.9.2 * @category Typeclass */ export interface Provide3C { readonly provideSome: (provided: A) => (hkt: Hkt) => Hkt readonly provideAll: ( provided: A, ) => (hkt: Hkt, E, B]>) => Hkt readonly useSome: Provide3C['provideSome'] readonly useAll: Provide3C['provideAll'] } /** * @since 0.9.2 * @category Typeclass */ export interface ProvideSome3C extends Pick, 'provideSome'> {} /** * @since 0.9.2 * @category Typeclass */ export interface ProvideAll3C extends Pick, 'provideAll'> {} /** * @since 0.9.2 * @category Typeclass */ export interface UseSome3C extends Pick, 'useSome'> {} /** * @since 0.9.2 * @category Typeclass */ export interface UseAll3C extends Pick, 'useAll'> {} /** * @since 0.9.2 * @category Typeclass */ export interface Provide4 { readonly provideSome: ( provided: A, ) => (hkt: Hkt) => Hkt readonly provideAll: ( provided: A, ) => (hkt: Hkt, E, B]>) => Hkt readonly useSome: Provide4['provideSome'] readonly useAll: Provide4['provideAll'] } /** * @since 0.9.2 * @category Typeclass */ export interface ProvideSome4 extends Pick, 'provideSome'> {} /** * @since 0.9.2 * @category Typeclass */ export interface ProvideAll4 extends Pick, 'provideAll'> {} /** * @since 0.9.2 * @category Typeclass */ export interface UseSome4 extends Pick, 'useSome'> {} /** * @since 0.9.2 * @category Typeclass */ export interface UseAll4 extends Pick, 'useAll'> {} /** * @since 0.9.2 * @category Type-level */ export type Provider = ( hkt: Hkt, ) => Hkt /** * @since 0.9.2 * @category Type-level */ export type Provider2 = ( hkt: Hkt, ) => Hkt /** * @since 0.9.2 * @category Type-level */ export type Provider3 = ( hkt: Hkt, ) => Hkt, A]> /** * @since 0.9.2 * @category Type-level */ export type Provider4 = ( hkt: Hkt, ) => Hkt, Added & R, ApplyVariance, A]> /** * @since 0.9.2 * @category Combinator */ export function useSomeWith( M: UseSome2 & Chain2, ): (provider: Hkt) => Provider2 export function useSomeWith( M: UseSome3 & Chain3, ): (provider: Hkt) => Provider3 export function useSomeWith( M: UseSome4 & Chain4, ): (provider: Hkt) => Provider4 export function useSomeWith( M: UseSome & Chain, ): (provider: HKT2) => Provider export function useSomeWith(M: UseSome & Chain) { return (provider: HKT2) => (hkt: HKT2) => pipe( provider, M.chain((removed) => pipe(hkt, M.useSome(removed))), ) } /** * @since 0.9.2 * @category Combinator */ export function provideSomeWith( M: ProvideSome2 & Chain2, ): (provider: Hkt) => Provider2 export function provideSomeWith( M: ProvideSome3 & Chain3, ): (provider: Hkt) => Provider3 export function provideSomeWith( M: ProvideSome4 & Chain4, ): (provider: Hkt) => Provider4 export function provideSomeWith( M: ProvideSome & Chain, ): (provider: HKT2) => Provider export function provideSomeWith(M: ProvideSome & Chain) { return (provider: HKT2) => (hkt: HKT2) => pipe( provider, M.chain((removed) => pipe(hkt, M.provideSome(removed))), ) } /** * @since 0.9.2 * @category Combinator */ export function useAllWith( M: UseAll2 & Chain2, ): (provider: Hkt) => (hkt: Hkt) => Hkt export function useAllWith( M: UseAll3 & Chain3, ): ( provider: Hkt, ) => (hkt: Hkt) => Hkt, B]> export function useAllWith( M: UseAll4 & Chain4, ): ( provider: Hkt, ) => ( hkt: Hkt, ) => Hkt, R, ApplyVariance, B]> export function useAllWith( M: UseAll & Chain, ): (provider: HKT2) => (hkt: HKT2) => HKT2 export function useAllWith(M: UseAll & Chain) { return (provider: HKT2) => (hkt: HKT2) => pipe( provider, M.chain((removed) => pipe(hkt, M.useAll(removed))), ) } /** * @since 0.9.2 * @category Combinator */ export function provideAllWith( M: ProvideAll2 & Chain2, ): (provider: Hkt) => (hkt: Hkt) => Hkt export function provideAllWith( M: ProvideAll3 & Chain3, ): ( provider: Hkt, ) => (hkt: Hkt) => Hkt, B]> export function provideAllWith( M: ProvideAll4 & Chain4, ): ( provider: Hkt, ) => ( hkt: Hkt, ) => Hkt, R, ApplyVariance, B]> export function provideAllWith( M: ProvideAll & Chain, ): (provider: HKT2) => (hkt: HKT2) => HKT2 export function provideAllWith(M: ProvideAll & Chain) { return (provider: HKT2) => (hkt: HKT2) => pipe( provider, M.chain((removed) => pipe(hkt, M.provideAll(removed))), ) } /** * @since 0.9.2 * @category Combinator */ export function askAndUse( M: UseAll2 & Chain2 & FromReader2, ): (hkt: Kind2) => Kind2> export function askAndUse( M: UseAll3 & Chain3 & FromReader3, ): (hkt: Kind3) => Kind3> export function askAndUse( M: UseAll4 & Chain4 & FromReader4, ): (hkt: Kind4) => Kind4> export function askAndUse( M: UseAll & Chain & FromReader, ): (hkt: HKT2) => HKT2> export function askAndUse(M: UseAll & Chain & FromReader) { return (hkt: HKT2) => pipe( M.fromReader((e: E) => e), M.map((e) => pipe(hkt, M.useAll(e))), ) } /** * @since 0.9.2 * @category Combinator */ export function askAndProvide( M: ProvideAll2 & Chain2 & FromReader2, ): (hkt: Kind2) => Kind2> export function askAndProvide( M: ProvideAll3 & Chain3 & FromReader3, ): (hkt: Kind3) => Kind3> export function askAndProvide( M: ProvideAll4 & Chain4 & FromReader4, ): (hkt: Kind4) => Kind4> export function askAndProvide( M: ProvideAll & Chain & FromReader, ): (hkt: HKT2) => HKT2> export function askAndProvide(M: ProvideAll & Chain & FromReader) { return (hkt: HKT2) => pipe( M.fromReader((e: E) => e), M.map((e) => pipe(hkt, M.provideAll(e))), ) }