import type * as HKT from "@principia/prelude/HKT"; import type * as Ac from "../Async"; import { _AI } from "../Async/constants"; import { _A, _E, _I, _R, _U, TaskInstructionTag } from "../Task/Task/constants"; import type * as T from "../Task/Task/model"; import { XPureIntegrationNotImplemented, XPureTaskIntegration } from "./integration"; export const URI = "XPure"; export type URI = typeof URI; export type V = HKT.V<"S", "_"> & HKT.V<"R", "-"> & HKT.V<"E", "+">; declare module "@principia/prelude/HKT" { interface URItoKind { readonly [URI]: XPure; } } export const _XPI = "_XPI"; export type _XPI = typeof _XPI; /** * `XPure` is a purely functional description of a computation * that requires an environment `R` and an initial state `S1` and may either * fail with an `E` or succeed with an updated state `S2` and an `A`. Because * of its polymorphism `XPure` can be used to model a variety of effects * including context, state, and failure. */ export abstract class XPure { readonly _tag = TaskInstructionTag.Integration; readonly _asyncTag = "XPure"; readonly _S1!: (_: S1) => void; readonly _S2!: () => S2; readonly [_U]!: T.URI; readonly [_E]!: () => E; readonly [_A]!: () => A; readonly [_R]!: (_: R) => void; get [_I](): T.Instruction { const xi = XPureTaskIntegration.get; if (xi._tag === "Some") { return xi.value(this as any)[_I]; } return XPureIntegrationNotImplemented; } get [_AI](): Ac.AsyncInstruction { return this as any; } get [_XPI](): Instruction { return this as any; } } export enum XPureInstructionTag { Succeed = "Succeed", Total = "Total", Partial = "Partial", Suspend = "Suspend", Fail = "Fail", Modify = "Modify", Chain = "Chain", Fold = "Fold", Asks = "Asks", Give = "Give" } export class SucceedInstruction extends XPure { readonly _xptag = XPureInstructionTag.Succeed; constructor(readonly value: A) { super(); } } export class TotalInstruction extends XPure { readonly _xptag = XPureInstructionTag.Total; constructor(readonly thunk: () => A) { super(); } } export class PartialInstruction extends XPure { readonly _xptag = XPureInstructionTag.Partial; constructor(readonly thunk: () => A, readonly onThrow: (u: unknown) => E) { super(); } } export class SuspendInstruction extends XPure { readonly _xptag = XPureInstructionTag.Suspend; constructor(readonly factory: () => XPure) { super(); } } export class FailInstruction extends XPure { readonly _xptag = XPureInstructionTag.Fail; constructor(readonly e: E) { super(); } } export class ModifyInstruction extends XPure { readonly _xptag = XPureInstructionTag.Modify; constructor(readonly run: (s1: S1) => readonly [S2, A]) { super(); } } export class ChainInstruction extends XPure { readonly _xptag = XPureInstructionTag.Chain; constructor(readonly ma: XPure, readonly f: (a: A) => XPure) { super(); } } export class FoldInstruction extends XPure< S1 & S5, S3 | S4, R & R1 & R2, E1 | E2, B | C > { readonly _xptag = XPureInstructionTag.Fold; constructor( readonly fa: XPure, readonly onFailure: (e: E) => XPure, readonly onSuccess: (a: A) => XPure ) { super(); } } export class AsksInstruction extends XPure { readonly _xptag = XPureInstructionTag.Asks; constructor(readonly f: (r: R0) => XPure) { super(); } } export class GiveInstruction extends XPure { readonly _xptag = XPureInstructionTag.Give; constructor(readonly fa: XPure, readonly r: R) { super(); } } export type Instruction = | SucceedInstruction | FailInstruction | ModifyInstruction | ChainInstruction | FoldInstruction | AsksInstruction | GiveInstruction | SuspendInstruction | TotalInstruction | PartialInstruction;