declare const HasURI: unique symbol
export interface Has {
readonly URI: typeof HasURI
readonly [K: symbol]: A
}
declare const TagURI: unique symbol
export interface Tag {
readonly [TagURI]: A
readonly key: symbol
}
export const tag = (): Tag => ({ key: Symbol() } as Tag)
export const singleton = (tag: Tag, a: A): Has =>
({ [tag.key]: a } as Has)
export const lookup =
(tag: Tag) =>
(has: Has) =>
has[tag.key]
export const upsertAt =
(tag: Tag, b: B) =>
<_Has extends Has>(has: _Has): _Has & Has => ({
...has,
...singleton(tag, b),
})
export const modifyAt =
(tag: Tag, f: (b: B) => B) =>
<_Has extends Has>(has: _Has) =>
upsertAt(tag, f(lookup(tag)(has)))(has)