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)])
);