UNPKG

@typed/fp

Version:

Data Structures and Resources for fp-ts

381 lines 9.21 kB
/** * `Ref` is an abstraction for managing data-driven applications using [Env](./Env.ts.md). * @since 0.11.0 */ import * as Ap from 'fp-ts/Apply'; import * as B from 'fp-ts/boolean'; import { EqStrict } from 'fp-ts/Eq'; import { flow, pipe } from 'fp-ts/function'; import { concatAll } from 'fp-ts/Monoid'; import * as RA from 'fp-ts/ReadonlyArray'; import * as E from './Env'; import * as EO from './EnvOption'; import * as KV from './KV'; import * as O from './Option'; import * as RS from './ReaderStream'; import * as RSO from './ReaderStreamOption'; import * as S from './struct'; const allBooleans = E.map(concatAll(B.MonoidAll)); /** * @since 0.11.0 * @category URI */ export const URI = '@typed/fp/Ref'; /** * @since 0.11.0 * @category Constructor */ export const fromKV = (kv) => ({ ...kv, get: KV.get(kv), has: KV.has(kv), set: KV.set(kv), update: KV.update(kv), remove: KV.remove(kv), values: KV.listenToValues(kv), }); /** * @since 0.11.0 * @category Constructor */ export const kv = flow(KV.make, fromKV); /** * @since 0.12.0 * @category Instance Constructor */ export const FromKV = { fromKV, }; /** * @since 0.11.0 * @category Combinator */ export const map = (f) => (ref) => ({ get: pipe(ref.get, E.map(f)), has: ref.has, set: flow(ref.set, E.map(f)), update: (g) => pipe(ref.get, E.map(f), E.chainW(g), E.chainW(ref.set), E.map(f)), remove: pipe(ref.remove, EO.map(f)), values: pipe(ref.values, RSO.map(f)), }); /** * @since 0.11.0 * @category Instance */ export const Functor = { map, }; /** * @since 0.11.0 * @category Combinator */ export const local = (f) => (ref) => ({ get: ref.get, has: ref.has, set: flow(f, ref.set), update: (g) => ref.update(flow(g, E.map(f))), remove: ref.remove, values: ref.values, }); /** * @since 0.12.2 * @category Combinator */ export const localE = (f) => (ref) => ({ get: ref.get, has: ref.has, set: flow(f, E.chainW(ref.set)), update: (g) => ref.update(flow(g, E.chainW(f))), remove: ref.remove, values: ref.values, }); /** * @since 0.11.0 * @category Combinator */ export const promap = (f, g) => (ref) => pipe(ref, local(f), map(g)); /** * @since 0.12.2 * @category Combinator */ export const promapE = (f, g) => (ref) => pipe(ref, localE(f), chainEnvK(g)); /** * @since 0.11.0 * @category Instance */ export const Profunctor = { map, promap, }; /** * @since 0.11.0 * @category Combinator */ export const ap = (fa) => (fab) => { const get = pipe(fab.get, E.apW(fa.get)); const set = (i) => pipe(i, fab.set, E.apW(fa.set(i))); return { get, has: pipe([], E.of, E.apTW(fa.has), E.apTW(fab.has), allBooleans), set: (i) => pipe(i, fab.set, E.apW(fa.set(i))), update: (f) => pipe(get, E.chainW(f), E.chainW(set)), remove: pipe(fab.remove, EO.apW(fa.remove)), values: pipe(fab.values, RSO.apW(fa.values)), }; }; /** * @since 0.11.0 * @category Instance */ export const Apply = { map, ap, }; /** * @since 0.11.0 * @category Combinator */ export const apFirst = Ap.apFirst(Apply); /** * @since 0.11.0 * @category Combinator */ export const apFirstW = apFirst; /** * @since 0.11.0 * @category Combinator */ export const apS = Ap.apS(Apply); /** * @since 0.11.0 * @category Combinator */ export const apSW = apS; /** * @since 0.11.0 * @category Combinator */ export const apSecond = Ap.apSecond(Apply); /** * @since 0.11.0 * @category Combinator */ export const apSecondW = apSecond; /** * @since 0.11.0 * @category Combinator */ export const apT = Ap.apT(Apply); /** * @since 0.11.0 * @category Combinator */ export const apTW = apT; /** * @since 0.11.0 * @category Typeclass Constructor */ export const getApplySemigroup = Ap.getApplySemigroup(Apply); /** * @since 0.11.0 * @category Combinator */ export const compose = (second) => (first) => ({ get: pipe(second.get, E.apFirstW(first.get)), has: pipe(first.has, E.tupled, E.apTW(second.has), allBooleans), set: flow(first.set, E.chainW(second.set)), update: (f) => pipe(second.get, E.chainW(f), E.chainW(first.set), E.chainW(second.set)), remove: pipe(second.remove, E.apFirstW(first.remove)), values: pipe(second.values, RS.mergeFirst( // Replicate all values into the second pipe(first.values, RS.chainFirstEnvK(O.matchW(() => second.remove, flow(second.set, EO.fromEnv))))), RS.skipRepeatsWith(O.getEq(EqStrict))), }); /** * @since 0.11.0 * @category Instance */ export const Semigroupoid = { compose, }; /** * @since 0.11.0 * @category Combinator */ export const provideSome = (provided) => (ref) => { return { get: pipe(ref.get, E.provideSome(provided)), has: pipe(ref.has, E.provideSome(provided)), set: flow(ref.set, E.provideSome(provided)), update: flow(ref.update, E.provideSome(provided)), remove: pipe(ref.remove, E.provideSome(provided)), values: pipe(ref.values, RS.provideSome(provided)), }; }; /** * @since 0.11.0 * @category Combinator */ export const provideAll = provideSome; /** * @since 0.11.0 * @category Combinator */ export const useSome = (provided) => (ref) => { return { get: pipe(ref.get, E.useSome(provided)), has: pipe(ref.has, E.useSome(provided)), set: flow(ref.set, E.useSome(provided)), update: flow(ref.update, E.useSome(provided)), remove: pipe(ref.remove, E.useSome(provided)), values: pipe(ref.values, RS.useSome(provided)), }; }; /** * @since 0.11.0 * @category Combinator */ export const useAll = useSome; /** * @since 0.11.0 * @category Instance */ export const UseSome = { useSome, }; /** * @since 0.11.0 * @category Instance */ export const UseAll = { useAll, }; /** * @since 0.11.0 * @category Instance */ export const ProvideSome = { provideSome, }; /** * @since 0.11.0 * @category Instance */ export const ProvideAll = { provideAll, }; /** * @since 0.11.0 * @category Instance */ export const Provide = { useSome, useAll, provideSome, provideAll, }; /** * @since 0.11.0 * @category Combinator */ export function chainEnvK(f) { return (ref) => ({ get: pipe(ref.get, E.chainW(f)), has: ref.has, set: flow(ref.set, E.chainW(f)), update: (g) => pipe(flow(f, E.chainW(g)), ref.update, E.chainW(f)), remove: pipe(ref.remove, EO.chainEnvK(f)), values: pipe(ref.values, RSO.chainEnvK(f)), }); } /** * @since 0.11.0 * @category Combinator */ export function chainFirstEnvK(f) { return (ref) => ({ get: pipe(ref.get, E.chainFirstW(f)), has: ref.has, set: flow(ref.set, E.chainFirstW(f)), update: flow(ref.update, E.chainFirstW(f)), remove: pipe(ref.remove, EO.chainFirstEnvK(f)), values: pipe(ref.values, RSO.chainFirstEnvK(f)), }); } /** * @since 0.11.0 * @category Combinator */ export function chainIOK(f) { return pipe(f, E.fromIOK, chainEnvK); } /** * @since 0.11.0 * @category Combinator */ export function chainFirstIOK(f) { return pipe(f, E.fromIOK, chainFirstEnvK); } /** * @since 0.11.0 * @category Combinator */ export function chainReaderK(f) { return pipe(f, E.fromReaderK, chainEnvK); } /** * @since 0.11.0 * @category Combinator */ export function chainFirstReaderK(f) { return pipe(f, E.fromReaderK, chainFirstEnvK); } /** * @since 0.11.0 * @category Combinator */ export function chainResumeK(f) { return pipe(f, E.fromResumeK, chainEnvK); } /** * @since 0.11.0 * @category Combinator */ export function chainFirstResumeK(f) { return pipe(f, E.fromResumeK, chainFirstEnvK); } /** * @since 0.11.0 * @category Combinator */ export function chainTaskK(f) { return pipe(f, E.fromTaskK, chainEnvK); } /** * @since 0.11.0 * @category Combinator */ export function chainFirstTaskK(f) { return pipe(f, E.fromTaskK, chainFirstEnvK); } /** * @since 0.11.0 * @category Combinator */ export function struct(properties) { const entries = Object.entries(properties); const zipAssign = flow(E.zipW, E.map((props) => Object.assign({}, ...props))); const get = pipe(entries, RA.map(([k, ref]) => pipe(ref.get, E.map((v) => S.make(k, v)))), zipAssign); const has = pipe(Object.values(properties), RA.map((ref) => ref.has), E.zipW, allBooleans); const set = (i) => pipe(i, Object.entries, RA.map(([k, v]) => pipe(v, properties[k].set, E.map((v) => S.make(k, v)))), zipAssign); const remove = pipe(entries, RA.map(([k, ref]) => pipe(ref.remove, EO.map((v) => S.make(k, v)))), E.zipW, E.map(flow(O.traverseReadonlyArrayWithIndex((_, a) => a), O.map((xs) => Object.assign({}, ...xs))))); const values = pipe(RS.combineAll(...pipe(entries, RA.map(([k, ref]) => pipe(ref.values, RSO.map((v) => S.make(k, v)))))), RS.map(flow(O.traverseReadonlyArrayWithIndex((_, a) => a), O.map((xs) => Object.assign({}, ...xs))))); return { get, has, set, update: (f) => pipe(get, E.chainW(f), E.chainW(set)), remove, values, }; } //# sourceMappingURL=Ref.js.map