UNPKG

@effect-ts/system

Version:

Effect-TS is a zero dependency set of libraries to write highly productive, purely functional TypeScript at scale.

326 lines (288 loc) 8.17 kB
var _a; // ets_tracing: off import * as T from "../../../Effect/index.mjs"; import * as E from "../../../Either/index.mjs"; export const STMTypeId = /*#__PURE__*/Symbol(); /** * `STM<R, E, A>` represents an effect that can be performed transactionally, * resulting in a failure `E` or a value `A` that may require an environment * `R` to execute. * * Software Transactional Memory is a technique which allows composition of arbitrary atomic operations. It is * the software analog of transactions in database systems. * * The API is lifted directly from the Haskell package Control.Concurrent.STM although the implementation does not * resemble the Haskell one at all. * [[http://hackage.haskell.org/package/stm-2.5.0.0/docs/Control-Concurrent-STM.html]] * * STM in Haskell was introduced in: * Composable memory transactions, by Tim Harris, Simon Marlow, Simon Peyton Jones, and Maurice Herlihy, in ACM * Conference on Principles and Practice of Parallel Programming 2005. * [[https://www.microsoft.com/en-us/research/publication/composable-memory-transactions/]] * * See also: * Lock Free Data Structures using STMs in Haskell, by Anthony Discolo, Tim Harris, Simon Marlow, Simon Peyton Jones, * Satnam Singh) FLOPS 2006: Eighth International Symposium on Functional and Logic Programming, Fuji Susono, JAPAN, * April 2006 * [[https://www.microsoft.com/en-us/research/publication/lock-free-data-structures-using-stms-in-haskell/]] * * The implemtation is based on the ZIO STM module, while JS environments have no race conditions from multiple threads * STM provides greater benefits for syncronisation of Fibers and transactional data-types can be quite useful. */ export class STM { constructor() { this[_a] = STMTypeId; } } _a = STMTypeId, T._R, T._E, T._A; export const STMEffectTypeId = /*#__PURE__*/Symbol(); export class STMEffect extends STM { constructor(f) { super(); this.f = f; this._typeId = STMEffectTypeId; } } export const STMOnFailureTypeId = /*#__PURE__*/Symbol(); export class STMOnFailure extends STM { constructor(stm, onFailure) { super(); this.stm = stm; this.onFailure = onFailure; this._typeId = STMOnFailureTypeId; } apply(a) { return new STMSucceedNow(a); } } export const STMOnRetryTypeId = /*#__PURE__*/Symbol(); export class STMOnRetry extends STM { constructor(stm, onRetry) { super(); this.stm = stm; this.onRetry = onRetry; this._typeId = STMOnRetryTypeId; } apply(a) { return new STMSucceedNow(a); } } export const STMOnSuccessTypeId = /*#__PURE__*/Symbol(); export class STMOnSuccess extends STM { constructor(stm, apply) { super(); this.stm = stm; this.apply = apply; this._typeId = STMOnSuccessTypeId; } } export const STMSucceedTypeId = /*#__PURE__*/Symbol(); export class STMSucceed extends STM { constructor(a) { super(); this.a = a; this._typeId = STMSucceedTypeId; } } export const STMSucceedNowTypeId = /*#__PURE__*/Symbol(); export class STMSucceedNow extends STM { constructor(a) { super(); this.a = a; this._typeId = STMSucceedNowTypeId; } } export const STMProvideSomeTypeId = /*#__PURE__*/Symbol(); export class STMProvideSome extends STM { constructor(stm, f) { super(); this.stm = stm; this.f = f; this._typeId = STMProvideSomeTypeId; } } /** * @ets_optimize remove */ export function concreteSTM(_) {// } export const FailExceptionTypeId = /*#__PURE__*/Symbol(); export class STMFailException { constructor(e) { this.e = e; this._typeId = FailExceptionTypeId; } } export function isFailException(u) { return typeof u === "object" && u != null && "_typeId" in u && u["_typeId"] === FailExceptionTypeId; } export const DieExceptionTypeId = /*#__PURE__*/Symbol(); export class STMDieException { constructor(e) { this.e = e; this._typeId = DieExceptionTypeId; } } export function isDieException(u) { return typeof u === "object" && u != null && "_typeId" in u && u["_typeId"] === DieExceptionTypeId; } export const RetryExceptionTypeId = /*#__PURE__*/Symbol(); export class STMRetryException { constructor() { this._typeId = RetryExceptionTypeId; } } export function isRetryException(u) { return typeof u === "object" && u != null && "_typeId" in u && u["_typeId"] === RetryExceptionTypeId; } // // primitive ops // /** * Returns an `STM` effect that succeeds with the specified value. */ export function succeed(a) { return new STMSucceedNow(a); } /** * Returns an `STM` effect that succeeds with the specified value. */ export function succeedWith(a) { return new STMSucceed(a); } /** * Returns a value that models failure in the transaction. */ export function fail(e) { return new STMEffect(() => { throw new STMFailException(e); }); } /** * Returns a value that models failure in the transaction. */ export function failWith(e) { return new STMEffect(() => { throw new STMFailException(e()); }); } /** * Kills the fiber running the effect. */ export function die(u) { return new STMEffect(() => { throw new STMDieException(u); }); } /** * Kills the fiber running the effect. */ export function dieWith(u) { return new STMEffect(() => { throw new STMDieException(u()); }); } /** * Maps the value produced by the effect. */ export function map_(self, f) { return chain_(self, a => succeed(f(a))); } /** * Maps the value produced by the effect. * * @ets_data_first map_ */ export function map(f) { return self => map_(self, f); } /** * Feeds the value produced by this effect to the specified function, * and then runs the returned effect as well to produce its results. */ export function chain_(self, f) { return new STMOnSuccess(self, f); } /** * Feeds the value produced by this effect to the specified function, * and then runs the returned effect as well to produce its results. * * @ets_data_first chain_ */ export function chain(f) { return self => chain_(self, f); } /** * Recovers from all errors. */ export function catchAll_(self, f) { return new STMOnFailure(self, f); } /** * Recovers from all errors. * * @ets_data_first catchAll_ */ export function catchAll(f) { return self => catchAll_(self, f); } /** * Effectfully folds over the `STM` effect, handling both failure and * success. */ export function foldM_(self, g, f) { return chain_(catchAll_(map_(self, E.right), e => map_(g(e), E.left)), E.fold(succeed, f)); } /** * Effectfully folds over the `STM` effect, handling both failure and * success. * * @ets_data_first foldM_ */ export function foldM(g, f) { return self => foldM_(self, g, f); } /** * Executes the specified finalization transaction whether or * not this effect succeeds. Note that as with all STM transactions, * if the full transaction fails, everything will be rolled back. */ export function ensuring_(self, finalizer) { return foldM_(self, e => chain_(finalizer, () => fail(e)), a => chain_(finalizer, () => succeed(a))); } /** * Executes the specified finalization transaction whether or * not this effect succeeds. Note that as with all STM transactions, * if the full transaction fails, everything will be rolled back. * * @ets_data_first ensuring_ */ export function ensuring(finalizer) { return self => ensuring_(self, finalizer); } /** * Abort and retry the whole transaction when any of the underlying * transactional variables have changed. */ export const retry = /*#__PURE__*/new STMEffect(() => { throw new STMRetryException(); }); /** * Returns an `STM` effect that succeeds with `Unit`. */ export const unit = /*#__PURE__*/succeed(undefined); /** * Provides some of the environment required to run this effect, * leaving the remainder `R0`. */ export function provideSome_(self, f) { return new STMProvideSome(self, f); } /** * Provides some of the environment required to run this effect, * leaving the remainder `R0`. * * @ets_data_first provideSome_ */ export function provideSome(f) { return self => provideSome_(self, f); } //# sourceMappingURL=primitives.mjs.map