import * as Effect from "effect/Effect" import { pipe } from "effect/Function" import * as Ref from "effect/Ref" import type * as Scope from "effect/Scope" interface Counter { acquire(): Effect.Effect incrementAcquire(): Effect.Effect incrementRelease(): Effect.Effect acquired(): Effect.Effect released(): Effect.Effect } class CounterImpl implements Counter { constructor(readonly ref: Ref.Ref) {} acquire(): Effect.Effect { return pipe( this.incrementAcquire(), Effect.andThen(Effect.addFinalizer(() => this.incrementRelease())), Effect.andThen(this.acquired()), Effect.uninterruptible ) } incrementAcquire(): Effect.Effect { return Ref.modify(this.ref, ([acquire, release]) => [acquire + 1, [acquire + 1, release] as const] as const) } incrementRelease(): Effect.Effect { return Ref.modify(this.ref, ([acquire, release]) => [release + 1, [acquire, release + 1] as const] as const) } acquired(): Effect.Effect { return pipe( Ref.get(this.ref), Effect.map((tuple) => tuple[0]) ) } released(): Effect.Effect { return pipe( Ref.get(this.ref), Effect.map((tuple) => tuple[1]) ) } } export const make = (): Effect.Effect => { return pipe( Ref.make([0, 0]), Effect.map((ref) => new CounterImpl(ref as any)) ) }