import { identity, pipe } from "../../Function"; import type { Option } from "../../Option"; import * as O from "../../Option"; import type * as T from "../Task/model"; import { ModifyFiberRefInstruction, NewFiberRefInstruction } from "../Task/model"; import type { FiberRef } from "./model"; export const fiberRef = (initial: A, fork: (a: A) => A, join: (a: A, a1: A) => A): FiberRef => ({ _tag: "FiberRef", initial, fork, join }); export const make = ( initial: A, onFork: (a: A) => A = identity, onJoin: (a: A, a1: A) => A = (_, a) => a ): T.IO> => new NewFiberRefInstruction(initial, onFork, onJoin); export const modify = (f: (a: A) => [B, A]) => (fiberRef: FiberRef): T.IO => new ModifyFiberRefInstruction(fiberRef, f); export const update = (f: (a: A) => A) => (fiberRef: FiberRef): T.IO => pipe( fiberRef, modify((v) => [undefined, f(v)]) ); export const set = (a: A) => (fiberRef: FiberRef): T.IO => pipe( fiberRef, modify((_) => [undefined, a]) ); export const get = (fiberRef: FiberRef) => pipe( fiberRef, modify((a) => [a, a]) ); export const getAndSet = (a: A) => (fiberRef: FiberRef) => pipe( fiberRef, modify((v) => [v, a]) ); export const getAndUpdate = (f: (a: A) => A) => (fiberRef: FiberRef) => pipe( fiberRef, modify((v) => [v, f(v)]) ); export const getAndUpdateSome = (f: (a: A) => Option) => (fiberRef: FiberRef) => pipe( fiberRef, modify((v) => [v, O.getOrElse_(f(v), () => v)]) );