import type { UnionToIntersection } from "@principia/prelude/Utils"; import { AtomicReference } from "../../support"; import type { Cause } from "../Exit/Cause"; import type { Managed } from "../Managed/model"; import type { DefaultEnv } from "../Task"; /* * ------------------------------------------- * Layer Model * ------------------------------------------- */ export const URI = "Layer"; export type URI = typeof URI; export abstract class Layer { readonly hash = new AtomicReference(Symbol()); readonly _R!: (_: R) => void; readonly _E!: () => E; readonly _Out!: () => A; setKey(hash: symbol) { this.hash.set(hash); return this; } ["_I"](): LayerInstruction { return this as any; } } declare module "@principia/prelude/HKT" { interface URItoKind { readonly [URI]: Layer; } } export enum LayerInstructionTag { Fold = "LayerFold", Map = "LayerMap", Chain = "LayerChain", Fresh = "LayerRefresh", Managed = "LayerManaged", Suspend = "LayerSuspend", MapBothPar = "LayerMapBothPar", AllPar = "LayerAllPar", AllSeq = "LayerAllSeq", MapBothSeq = "LayerMapBothSeq" } /** * Type level bound to make sure a layer is complete */ export const main = (layer: Layer) => layer; export type LayerInstruction = | LayerFoldInstruction | LayerMapInstruction | LayerChainInstruction | LayerChainInstruction | LayerFreshInstruction | LayerManagedInstruction | LayerSuspendInstruction | LayerMapBothParInstruction | LayerMapBothSeqInstruction | LayerAllParInstruction[]> | LayerAllSeqInstruction[]>; export class LayerFoldInstruction extends Layer< RIn & R, E1 | E2, ROut1 | ROut2 > { readonly _tag = LayerInstructionTag.Fold; constructor( readonly layer: Layer, readonly onFailure: Layer], E1, ROut1>, readonly onSuccess: Layer ) { super(); } } export class LayerMapInstruction extends Layer { readonly _tag = LayerInstructionTag.Map; constructor(readonly layer: Layer, readonly f: (a: A) => B) { super(); } } export class LayerChainInstruction extends Layer { readonly _tag = LayerInstructionTag.Chain; constructor(readonly layer: Layer, readonly f: (a: A) => Layer) { super(); } } export class LayerFreshInstruction extends Layer { readonly _tag = LayerInstructionTag.Fresh; constructor(readonly layer: Layer) { super(); } } export class LayerManagedInstruction extends Layer { readonly _tag = LayerInstructionTag.Managed; constructor(readonly managed: Managed) { super(); } } export class LayerSuspendInstruction extends Layer { readonly _tag = LayerInstructionTag.Suspend; constructor(readonly factory: () => Layer) { super(); } } export type MergeR[]> = UnionToIntersection< { [k in keyof Ls]: [Ls[k]] extends [Layer] ? (unknown extends X ? never : X) : never; }[number] >; export type MergeE[]> = { [k in keyof Ls]: [Ls[k]] extends [Layer] ? X : never; }[number]; export type MergeA[]> = UnionToIntersection< { [k in keyof Ls]: [Ls[k]] extends [Layer] ? (unknown extends X ? never : X) : never; }[number] >; export class LayerMapBothParInstruction extends Layer { readonly _tag = LayerInstructionTag.MapBothPar; constructor(readonly layer: Layer, readonly that: Layer, readonly f: (a: A, b: B) => C) { super(); } } export class LayerAllParInstruction[]> extends Layer< MergeR, MergeE, MergeA > { readonly _tag = LayerInstructionTag.AllPar; constructor(readonly layers: Ls & { 0: Layer }) { super(); } } export class LayerMapBothSeqInstruction extends Layer { readonly _tag = LayerInstructionTag.MapBothSeq; constructor(readonly layer: Layer, readonly that: Layer, readonly f: (a: A, b: B) => C) { super(); } } export class LayerAllSeqInstruction[]> extends Layer< MergeR, MergeE, MergeA > { readonly _tag = LayerInstructionTag.AllSeq; constructor(readonly layers: Ls & { 0: Layer }) { super(); } }