UNPKG

@typed/fp

Version:

Data Structures and Resources for fp-ts

137 lines (118 loc) 3.22 kB
/** * RefMap is a collection of helpers for working with Refs that manage a ReadonlyMap. * @since 0.12.0 */ import { Endomorphism } from 'fp-ts/Endomorphism' import { Eq } from 'fp-ts/Eq' import * as O from 'fp-ts/Option' import { Predicate } from 'fp-ts/Predicate' import * as RM from 'fp-ts/ReadonlyMap' import { fst, snd } from 'fp-ts/Tuple2' import * as E from './Env' import * as EO from './EnvOption' import { flow, pipe } from './function' import * as Ref from './Ref' /** * @since 0.12.0 * @category Model */ export interface RefMap<E, K, V> extends Ref.Ref<E, ReadonlyMap<K, V>> {} /** * @since 0.12.0 * @category Combinator */ export const deleteAt = <K>(Eq: Eq<K>) => { return (key: K) => { const deleteAtKey = RM.deleteAt(Eq)(key) return <E, V>(rm: RefMap<E, K, V>) => pipe(rm.get, E.map(deleteAtKey), EO.chainFirstEnvK(rm.set)) } } /** * @since 0.12.0 * @category Combinator */ export function filter<A>(predicate: Predicate<A>) { return <E, K>(rm: RefMap<E, K, A>) => rm.update(flow(RM.filter(predicate), E.of)) } /** * @since 0.12.0 * @category Combinator */ export function filterWithIndex<K, V>(predicate: (k: K, v: V) => boolean) { return <E>(rm: RefMap<E, K, V>) => rm.update(flow(RM.filterWithIndex(predicate), E.of)) } /** * @since 0.12.0 * @category Combinator */ export const insertAt = <K>(Eq: Eq<K>) => { return <V>(key: K, value: V) => { const insertAtKey = RM.insertAt(Eq)(key, value) return <E>(rm: RefMap<E, K, V>) => pipe(rm.get, E.map(insertAtKey), EO.chainFirstEnvK(rm.set)) } } /** * @since 0.12.0 * @category Combinator */ export const modifyAt = <K>(Eq: Eq<K>) => { return <V>(key: K, f: Endomorphism<V>) => { const modifyAtKey = RM.modifyAt(Eq)(key, f) return <E>(rm: RefMap<E, K, V>) => pipe(rm.get, E.map(modifyAtKey), EO.chainFirstEnvK(rm.set)) } } /** * @since 0.12.0 * @category Combinator */ export const pop = <K>(Eq: Eq<K>) => (k: K) => { const popWithKey = RM.pop(Eq)(k) return <E, A>(rm: RefMap<E, K, A>): E.Env<E, O.Option<A>> => pipe(rm.get, E.map(popWithKey), EO.chainFirstEnvK(flow(snd, rm.set)), EO.map(fst)) } /** * @since 0.12.0 * @category Combinator */ export const updateAt = <K>(Eq: Eq<K>) => { return <V>(key: K, value: V) => { const updateAtKey = RM.updateAt(Eq)(key, value) return <E>(rm: RefMap<E, K, V>) => pipe(rm.get, E.map(updateAtKey), EO.chainFirstEnvK(rm.set)) } } /** * @since 0.12.0 * @category Combinator */ export const upsertAt = <K>(Eq: Eq<K>) => { return <V>(key: K, value: V) => { const upsertAtKey = RM.upsertAt(Eq)(key, value) return <E>(rm: RefMap<E, K, V>) => rm.update(flow(upsertAtKey, E.of)) } } /** * @since 0.12.1 * @category Combinator */ export const getOrCreate = <K>(Eq: Eq<K>) => { return <E1, V>(key: K, create: E.Env<E1, V>) => { const lookup = RM.lookup(Eq)(key) const upsert = upsertAt(Eq) return <E2>(rm: RefMap<E2, K, V>) => pipe( rm.get, E.map(lookup), EO.matchEW( () => pipe( create, E.chainFirstW((v) => pipe(rm, upsert(key, v))), ), E.of, ), ) } }