UNPKG

@typed/fp

Version:

Data Structures and Resources for fp-ts

555 lines 11.6 kB
/** * `Env` is the core of the higher-level modules like [Ref](./Ref.ts.md) and is a `ReaderT` of [Resume](./Resume.ts.md); but * to be honest, being used so much, I didn't like writing `ReaderResume<E, A>` and chose to shorten to * `Env<E, A>` for the "environmental" quality Reader provides. Combining Reader and Resume allows for * creating APIs capable of utilizing dependency injection for their configuration and testability * while still combining your sync/async workflows. * * While designing application APIs it is often better to describe the logic of your system separate * from the implementation details. `Env` or rather `Reader` helps you accomplish this through the * [Dependency Inversion Principle](https://alexnault.dev/dependency-inversion-principle-in-functional-typescript). * This principle is one of the easiest ways to begin improving any codebase. * * @since 0.9.2 */ import { disposeNone } from '@most/disposable'; import * as Alt_ from 'fp-ts/Alt'; import * as FpApplicative from 'fp-ts/Applicative'; import * as Ap from 'fp-ts/Apply'; import * as FpChain from 'fp-ts/Chain'; import * as FIO from 'fp-ts/FromIO'; import * as FR from 'fp-ts/FromReader'; import * as FT from 'fp-ts/FromTask'; import * as FN from 'fp-ts/function'; import { bindTo as bindTo_, flap as flap_, tupled as tupled_ } from 'fp-ts/Functor'; import * as RT from 'fp-ts/ReaderT'; import * as RA from 'fp-ts/ReadonlyArray'; import { traverse } from 'fp-ts/ReadonlyArray'; import * as FRe from './FromResume'; import * as P from './Provide'; import * as R from './Resume'; import * as St from './struct'; /** * @since 0.9.2 * @category Combinator */ export const ap = RT.ap(R.Apply); /** * @since 0.9.2 * @category Combinator */ export const apW = RT.ap(R.Apply); /** * @since 0.9.2 * @category Combinator */ export const chain = RT.chain(R.Chain); /** * @since 0.9.2 * @category Combinator */ export const chainW = RT.chain(R.Chain); /** * @since 0.9.2 * @category Constructor */ export const fromReader = RT.fromReader(R.Pointed); /** * @since 0.9.2 * @category Combinator */ export const map = RT.map(R.Functor); /** * @since 0.9.2 * @category Combinator */ export const tap = (f) => (fa) => FN.pipe(fa, map((a) => { f(a); return a; })); /** * @since 0.9.2 * @category Combinator */ export const constant = FN.flow(FN.constant, map); /** * @since 0.9.2 * @category Constructor */ export const of = RT.of(R.Pointed); /** * @since 0.9.2 * @category Constructor */ export const asksIOK = RT.fromNaturalTransformation(R.fromIO); /** * @since 0.9.2 * @category Constructor */ export const asksTaskK = RT.fromNaturalTransformation(R.fromTask); /** * @since 0.9.2 * @category Combinator */ export function chainRec(f) { return (value) => (env) => R.chainRec((a) => f(a)(env))(value); } /** * @since 0.9.2 * @category URI */ export const URI = '@typed/fp/Env'; /** * @since 0.9.2 * @category Instance */ export const Pointed = { of, }; /** * @since 0.9.2 * @category Instance */ export const Functor = { URI, map, }; /** * @since 0.9.2 * @category Combinator */ export const flap = flap_(Functor); /** * @since 0.9.2 * @category Instance */ export const Apply = { ...Functor, ap, }; /** * @since 0.9.2 * @category Combinator */ export const apS = Ap.apS(Apply); /** * @since 0.9.2 * @category Combinator */ export const apSW = apS; /** * @since 0.9.2 * @category Combinator */ export const apT = Ap.apT(Apply); /** * @since 0.9.2 * @category Combinator */ export const apTW = apT; /** * @since 0.9.2 * @category Combinator */ export const apFirst = Ap.apFirst(Apply); /** * @since 0.9.2 * @category Combinator */ export const apFirstW = apFirst; /** * @since 0.9.2 * @category Combinator */ export const apSecond = Ap.apSecond(Apply); /** * @since 0.9.2 * @category Combinator */ export const apSecondW = apSecond; /** * @since 0.9.2 * @category Typeclass Constructor */ export const getSemigroup = Ap.getApplySemigroup(Apply); /** * @since 0.9.2 * @category Instance */ export const Applicative = { ...Apply, ...Pointed, }; /** * @since 0.9.2 * @category Typeclass Constructor */ export const getMonoid = FpApplicative.getApplicativeMonoid(Applicative); /** * @since 0.9.2 * @category Instance */ export const Chain = { ...Functor, chain, }; /** * @since 0.9.2 * @category Combinator */ export const chainFirst = FpChain.chainFirst(Chain); /** * @since 0.9.2 * @category Combinator */ export const chainFirstW = chainFirst; /** * @since 0.9.2 * @category Combinator */ export const flattenW = chain(FN.identity); /** * @since 0.9.2 * @category Combinator */ export const flatten = chain(FN.identity); /** * @since 0.9.2 * @category Instance */ export const Monad = { ...Chain, ...Pointed, }; /** * @since 0.9.2 * @category Instance */ export const ChainRec = { URI, chainRec, }; /** * @since 0.9.2 * @category Instance */ export const MonadRec = { ...Monad, chainRec, }; /** * @since 0.9.2 * @category Instance */ export const FromReader = { fromReader: (reader) => (e) => R.sync(() => reader(e)), }; /** * @since 0.9.2 * @category Combinator */ export const raceW = (a) => (b) => (e) => R.race(a(e))(b(e)); /** * @since 0.9.2 * @category Combinator */ export const race = (a) => (b) => (e) => R.race(a(e))(b(e)); /** * @since 0.9.2 * @category Instance */ export const Alt = { ...Functor, alt: (snd) => (fst) => raceW(fst)(snd()), }; /** * @since 0.9.2 * @category Combinator */ export const alt = Alt.alt; /** * @since 0.9.2 * @category Combinator */ export const altW = alt; /** * @since 0.9.2 * @category Combinator */ export const altAll = Alt_.altAll(Alt); /** * @since 0.9.2 * @category Constructor */ export const fromIO = fromReader; /** * @since 0.9.2 * @category Instance */ export const FromIO = { URI, fromIO, }; /** * @since 0.9.2 * @category Instance */ export const FromTask = { ...FromIO, fromTask: (task) => () => R.fromTask(task), }; /** * @since 0.9.2 * @category Constructor */ export const fromTask = FromTask.fromTask; /** * @since 0.9.2 * @category Constructor */ export const fromResume = FN.constant; /** * @since 0.9.2 * @category Combinator */ export const FromResume = { fromResume, }; /** * @since 0.9.2 * @category Combinator */ export const useSome = (provided) => (env) => (e) => env({ ...e, ...provided }); /** * @since 0.9.2 * @category Combinator */ export const provideSome = (provided) => (env) => (e) => env({ ...provided, ...e }); /** * @since 0.9.2 * @category Combinator */ export const useAll = (provided) => (env) => () => env(provided); /** * @since 0.9.2 * @category Combinator */ export const provideAll = (provided) => (env) => (e) => { var _a; return env({ ...provided, ...((_a = e) !== null && _a !== void 0 ? _a : {}) }); }; /** * @since 0.9.2 * @category Instance */ export const UseSome = { useSome, }; /** * @since 0.9.2 * @category Instance */ export const UseAll = { useAll, }; /** * @since 0.9.2 * @category Instance */ export const ProvideSome = { provideSome, }; /** * @since 0.9.2 * @category Instance */ export const ProvideAll = { provideAll, }; /** * @since 0.9.2 * @category Combinator */ export const provideAllWith = P.provideAllWith({ ...ProvideAll, ...Chain }); /** * @since 0.9.2 * @category Combinator */ export const useAllWith = P.useAllWith({ ...UseAll, ...Chain }); /** * @since 0.9.2 * @category Combinator */ export const provideSomeWith = P.provideSomeWith({ ...ProvideSome, ...Chain }); /** * @since 0.9.2 * @category Combinator */ export const useSomeWith = P.useSomeWith({ ...UseSome, ...Chain }); /** * @since 0.9.2 * @category Combinator */ export const askAndUse = P.askAndUse({ ...UseAll, ...Chain, ...FromReader }); /** * @since 0.9.2 * @category Combinator */ export const askAndProvide = P.askAndProvide({ ...ProvideAll, ...Chain, ...FromReader }); /** * @since 0.9.2 * @category Combinator */ export const toResume = FN.flow(askAndUse, map((e) => e({}))); /** * @since 0.9.2 * @category Instance */ export const Provide = { useSome, useAll, provideSome, provideAll, }; /** * @since 0.9.2 * @category Constructor */ export const Do = fromIO(() => Object.create(null)); /** * @since 0.9.2 * @category Combinator */ export const bindTo = bindTo_(Functor); /** * @since 0.9.2 * @category Combinator */ export const bind = FpChain.bind(Monad); /** * @since 0.9.2 * @category Combinator */ export const bindW = FpChain.bind(Monad); /** * @since 0.9.2 * @category Combinator */ export const tupled = tupled_(Functor); /** * @since 0.9.2 * @category Constructor */ export const ask = FR.ask(FromReader); /** * @since 0.9.2 * @category Constructor */ export const asks = FR.asks(FromReader); /** * @since 0.9.2 * @category Constructor */ export const asksE = FN.flow(asks, flattenW); /** * @since 0.9.2 * @category Combinator */ export const chainReaderK = FR.chainReaderK(FromReader, Chain); /** * @since 0.9.2 * @category Constructor */ export const fromReaderK = FR.fromReaderK(FromReader); /** * @since 0.9.2 * @category Combinator */ export const chainFirstResumeK = FRe.chainFirstResumeK(FromResume, Chain); /** * @since 0.9.2 * @category Combinator */ export const chainResumeK = FRe.chainResumeK(FromResume, Chain); /** * @since 0.9.2 * @category Constructor */ export const fromResumeK = FRe.fromResumeK(FromResume); /** * @since 0.9.2 * @category Combinator */ export const chainFirstTaskK = FT.chainFirstTaskK(FromTask, Chain); /** * @since 0.9.2 * @category Combinator */ export const chainTaskK = FT.chainTaskK(FromTask, Chain); /** * @since 0.9.2 * @category Constructor */ export const fromTaskK = FT.fromTaskK(FromTask); /** * @since 0.9.2 * @category Combinator */ export const chainFirstIOK = FIO.chainFirstIOK(FromIO, Chain); /** * @since 0.9.2 * @category Combinator */ export const chainIOK = FIO.chainIOK(FromIO, Chain); /** * @since 0.9.2 * @category Constructor */ export const fromIOK = FIO.fromIOK(FromIO); /** * @since 0.9.2 * @category Combinator */ export const zip = traverse(Applicative)((x) => x); /** * @since 0.9.2 * @category Combinator */ export const zipW = zip; /** * @since 0.9.2 * @category Combinator */ export const combineAll = (...envs) => zipW(envs); /** * @since 0.11.0 * @category Combinator */ export const combineStruct = (props) => FN.pipe(combineAll(...FN.pipe(Object.entries(props), RA.map(([k, env]) => FN.pipe(env, map((v) => St.make(k, v)))))), map((o) => Object.assign({}, ...o))); /** * @since 0.9.2 * @category Execution */ export const runWith = (f) => (requirements) => (env) => FN.pipe(requirements, env, R.run(f)); /** * @since 0.9.2 * @category Execution */ export const execWith = runWith(disposeNone); /** * Construct an Env to a lazily-defined Env-based effect that must be provided later. * Does not support functions which require type-parameters as they will resolve to unknown, due * to limitations in TS, if you need this maybe use [asksE](#askse) * @since 0.9.2 * @category Constructor */ export const op = () => (key) => { function operation(...args) { return FN.pipe(ask(), chain((e) => e[key](...args))); } operation.key = key; return operation; }; /** * @since 0.9.2 * @category Combinator */ export const toResumeK = (envK) => FN.pipe(ask(), map((e) => (...args) => FN.pipe(e, envK(...args)))); //# sourceMappingURL=Env.js.map