"use strict"
var __createBinding =
  (this && this.__createBinding) ||
  (Object.create
    ? function (o, m, k, k2) {
        if (k2 === undefined) k2 = k
        Object.defineProperty(o, k2, {
          enumerable: true,
          get: function () {
            return m[k]
          }
        })
      }
    : function (o, m, k, k2) {
        if (k2 === undefined) k2 = k
        o[k2] = m[k]
      })
var __setModuleDefault =
  (this && this.__setModuleDefault) ||
  (Object.create
    ? function (o, v) {
        Object.defineProperty(o, "default", { enumerable: true, value: v })
      }
    : function (o, v) {
        o["default"] = v
      })
var __importStar =
  (this && this.__importStar) ||
  function (mod) {
    if (mod && mod.__esModule) return mod
    var result = {}
    if (mod != null)
      for (var k in mod)
        if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
          __createBinding(result, mod, k)
    __setModuleDefault(result, mod)
    return result
  }
Object.defineProperty(exports, "__esModule", { value: true })
exports.continueOrFail =
  exports.continueOrFail_ =
  exports.continueOrFailM =
  exports.continueOrFailM_ =
  exports.continueOrRetry =
  exports.continueOrRetry_ =
  exports.continueOrRetryM =
  exports.continueOrRetryM_ =
  exports.catchSome =
  exports.catchSome_ =
  exports.catchTag_ =
  exports.catchTag =
  exports.catch_ =
  exports.bimap =
  exports.bimap_ =
  exports.asSomeError =
  exports.asSome =
  exports.as =
  exports.as_ =
  exports.andThen =
  exports.andThen_ =
  exports.absolve =
  exports.accessM =
  exports.access =
  exports.MaxFrames =
  exports.catch =
  exports.dieWith =
  exports.die =
  exports.unit =
  exports.succeedWith =
  exports.succeed =
  exports.STMRetryException =
  exports.STMFailException =
  exports.STMEffect =
  exports.STM =
  exports.retry =
  exports.provideSome_ =
  exports.provideSome =
  exports.map_ =
  exports.map =
  exports.foldM_ =
  exports.foldM =
  exports.failWith =
  exports.fail =
  exports.ensuring_ =
  exports.ensuring =
  exports.chain_ =
  exports.chain =
  exports.catchAll_ =
  exports.catchAll =
    void 0
exports.join_ =
  exports.join =
  exports.leftOrFailException =
  exports.leftOrFail =
  exports.leftOrFail_ =
  exports.left =
  exports.isSuccess =
  exports.isFailure =
  exports.ignore =
  exports.head =
  exports.get =
  exports.fromEither =
  exports.fromEitherWith =
  exports.forEach =
  exports.forEach_ =
  exports.flattenErrorOption_ =
  exports.flattenErrorOption =
  exports.flattenErrorOptionWith_ =
  exports.flattenErrorOptionWith =
  exports.flatten =
  exports.fold =
  exports.fold_ =
  exports.flipWith_ =
  exports.flipWith =
  exports.flip =
  exports.filterOrDieMessage_ =
  exports.filterOrDieMessage =
  exports.filterOrElse_ =
  exports.filterOrElse =
  exports.filterOrFail_ =
  exports.filterOrFail =
  exports.filterOrDie_ =
  exports.filterOrDie =
  exports.eventually =
  exports.environment =
  exports.either =
  exports.dieMessageWith =
  exports.dieMessage =
  exports.commitEither =
  exports.commit =
  exports.compose =
  exports.compose_ =
  exports.check =
  exports.checkWith =
  exports.chainError_ =
  exports.chainError =
  exports.continueOrFailWith =
  exports.continueOrFailWith_ =
  exports.continueOrFailWithM =
  exports.continueOrFailWithM_ =
    void 0
exports.zipWith =
  exports.zipWith_ =
  exports.toLeft =
  exports.toLeftWith =
  exports.tap =
  exports.tap_ =
  exports.suspend =
  exports.repeatWhile =
  exports.repeatWhile_ =
  exports.repeatUntil =
  exports.repeatUntil_ =
  exports.provideAll =
  exports.provideAll_ =
  exports.mapError =
  exports.mapError_ =
  exports.joinEither =
  exports.joinEither_ =
    void 0
// tracing: off
require("../../Operator")
const Cause_1 = require("../../Cause")
const T = __importStar(require("../../Effect"))
const E = __importStar(require("../../Either"))
const Function_1 = require("../../Function")
const GlobalExceptions_1 = require("../../GlobalExceptions")
const O = __importStar(require("../../Option"))
const AtomicBoolean_1 = require("../../Support/AtomicBoolean")
const P = __importStar(require("./_internal/primitives"))
const Journal_1 = require("./Journal")
const TryCommit_1 = require("./TryCommit")
const TxnId_1 = require("./TxnId")
var primitives_1 = require("./_internal/primitives")
Object.defineProperty(exports, "catchAll", {
  enumerable: true,
  get: function () {
    return primitives_1.catchAll
  }
})
Object.defineProperty(exports, "catchAll_", {
  enumerable: true,
  get: function () {
    return primitives_1.catchAll_
  }
})
Object.defineProperty(exports, "chain", {
  enumerable: true,
  get: function () {
    return primitives_1.chain
  }
})
Object.defineProperty(exports, "chain_", {
  enumerable: true,
  get: function () {
    return primitives_1.chain_
  }
})
Object.defineProperty(exports, "ensuring", {
  enumerable: true,
  get: function () {
    return primitives_1.ensuring
  }
})
Object.defineProperty(exports, "ensuring_", {
  enumerable: true,
  get: function () {
    return primitives_1.ensuring_
  }
})
Object.defineProperty(exports, "fail", {
  enumerable: true,
  get: function () {
    return primitives_1.fail
  }
})
Object.defineProperty(exports, "failWith", {
  enumerable: true,
  get: function () {
    return primitives_1.failWith
  }
})
Object.defineProperty(exports, "foldM", {
  enumerable: true,
  get: function () {
    return primitives_1.foldM
  }
})
Object.defineProperty(exports, "foldM_", {
  enumerable: true,
  get: function () {
    return primitives_1.foldM_
  }
})
Object.defineProperty(exports, "map", {
  enumerable: true,
  get: function () {
    return primitives_1.map
  }
})
Object.defineProperty(exports, "map_", {
  enumerable: true,
  get: function () {
    return primitives_1.map_
  }
})
Object.defineProperty(exports, "provideSome", {
  enumerable: true,
  get: function () {
    return primitives_1.provideSome
  }
})
Object.defineProperty(exports, "provideSome_", {
  enumerable: true,
  get: function () {
    return primitives_1.provideSome_
  }
})
Object.defineProperty(exports, "retry", {
  enumerable: true,
  get: function () {
    return primitives_1.retry
  }
})
Object.defineProperty(exports, "STM", {
  enumerable: true,
  get: function () {
    return primitives_1.STM
  }
})
Object.defineProperty(exports, "STMEffect", {
  enumerable: true,
  get: function () {
    return primitives_1.STMEffect
  }
})
Object.defineProperty(exports, "STMFailException", {
  enumerable: true,
  get: function () {
    return primitives_1.STMFailException
  }
})
Object.defineProperty(exports, "STMRetryException", {
  enumerable: true,
  get: function () {
    return primitives_1.STMRetryException
  }
})
Object.defineProperty(exports, "succeed", {
  enumerable: true,
  get: function () {
    return primitives_1.succeed
  }
})
Object.defineProperty(exports, "succeedWith", {
  enumerable: true,
  get: function () {
    return primitives_1.succeedWith
  }
})
Object.defineProperty(exports, "unit", {
  enumerable: true,
  get: function () {
    return primitives_1.unit
  }
})
Object.defineProperty(exports, "die", {
  enumerable: true,
  get: function () {
    return primitives_1.die
  }
})
Object.defineProperty(exports, "dieWith", {
  enumerable: true,
  get: function () {
    return primitives_1.dieWith
  }
})
exports.MaxFrames = 200
/**
 * Accesses the environment of the transaction.
 */
function access(f) {
  return P.map_(environment(), f)
}
exports.access = access
/**
 * Accesses the environment of the transaction to perform a transaction.
 */
function accessM(f) {
  return P.chain_(environment(), f)
}
exports.accessM = accessM
/**
 * Submerges the error case of an `Either` into the `STM`. The inverse
 * operation of `STM.either`.
 */
function absolve(z) {
  return P.chain_(z, fromEither)
}
exports.absolve = absolve
/**
 * Propagates the given environment to self.
 */
function andThen_(self, that) {
  return P.chain_(self, (a) => provideAll_(that, a))
}
exports.andThen_ = andThen_
/**
 * Propagates the given environment to self.
 *
 * @dataFirst andThen_
 */
function andThen(that) {
  return (self) => andThen_(self, that)
}
exports.andThen = andThen
/**
 * Maps the success value of this effect to the specified constant value.
 */
function as_(self, b) {
  return P.map_(self, () => b)
}
exports.as_ = as_
/**
 * Maps the success value of this effect to the specified constant value.
 *
 * @dataFirst as_
 */
function as(b) {
  return (self) => as_(self, b)
}
exports.as = as
/**
 * Maps the success value of this effect to an optional value.
 */
function asSome(self) {
  return P.map_(self, O.some)
}
exports.asSome = asSome
/**
 * Maps the error value of this effect to an optional value.
 */
function asSomeError(self) {
  return mapError_(self, O.some)
}
exports.asSomeError = asSomeError
/**
 * Returns an `STM` effect whose P.failure and success channels have been mapped by
 * the specified pair of functions, `f` and `g`.
 */
function bimap_(self, g, f) {
  return P.foldM_(
    self,
    (e) => P.fail(g(e)),
    (a) => P.succeed(f(a))
  )
}
exports.bimap_ = bimap_
/**
 * Returns an `STM` effect whose P.failure and success channels have been mapped by
 * the specified pair of functions, `f` and `g`.
 *
 * @dataFirst bimap_
 */
function bimap(g, f) {
  return (self) => bimap_(self, g, f)
}
exports.bimap = bimap
/**
 * Recovers from specified error.
 *
 * @dataFirst catch_
 */
function _catch(tag, k, f, __trace) {
  return (self) =>
    P.catchAll_(self, (e) => {
      if (tag in e && e[tag] === k) {
        return f(e)
      }
      return P.fail(e)
    })
}
exports.catch = _catch
/**
 * Recovers from specified error.
 */
function catch_(self, tag, k, f) {
  return P.catchAll_(self, (e) => {
    if (tag in e && e[tag] === k) {
      return f(e)
    }
    return P.fail(e)
  })
}
exports.catch_ = catch_
/**
 * Recovers from specified error.
 *
 * @dataFirst catchTag_
 */
function catchTag(k, f, __trace) {
  return (self) => catchTag_(self, k, f)
}
exports.catchTag = catchTag
/**
 * Recovers from specified error.
 */
function catchTag_(self, k, f) {
  return P.catchAll_(self, (e) => {
    if ("_tag" in e && e["_tag"] === k) {
      return f(e)
    }
    return P.fail(e)
  })
}
exports.catchTag_ = catchTag_
/**
 * Recovers from some or all of the error cases.
 */
function catchSome_(self, f) {
  return P.catchAll_(self, (e) => O.fold_(f(e), () => P.fail(e), Function_1.identity))
}
exports.catchSome_ = catchSome_
/**
 * Recovers from some or all of the error cases.
 *
 * @dataFirst catchSome_
 */
function catchSome(f) {
  return (self) => catchSome_(self, f)
}
exports.catchSome = catchSome
/**
 * Simultaneously filters and flatMaps the value produced by this effect.
 * Continues on the effect returned from pf.
 */
function continueOrRetryM_(fa, pf) {
  return P.chain_(fa, (a) => O.getOrElse_(pf(a), () => P.retry))
}
exports.continueOrRetryM_ = continueOrRetryM_
/**
 * Simultaneously filters and flatMaps the value produced by this effect.
 * Continues on the effect returned from pf.
 *
 * @dataFirst continueOrRetryM_
 */
function continueOrRetryM(pf) {
  return (fa) => continueOrRetryM_(fa, pf)
}
exports.continueOrRetryM = continueOrRetryM
/**
 * Fail with `e` if the supplied `PartialFunction` does not match, otherwise
 * succeed with the returned value.
 */
function continueOrRetry_(fa, pf) {
  return continueOrRetryM_(fa, (x) => O.map_(pf(x), P.succeed))
}
exports.continueOrRetry_ = continueOrRetry_
/**
 * Fail with `e` if the supplied `PartialFunction` does not match, otherwise
 * succeed with the returned value.
 *
 * @dataFirst continueOrRetry_
 */
function continueOrRetry(pf) {
  return (fa) => continueOrRetry_(fa, pf)
}
exports.continueOrRetry = continueOrRetry
/**
 * Fail with `e` if the supplied `PartialFunction` does not match, otherwise
 * continue with the returned value.
 */
function continueOrFailM_(fa, e, pf) {
  return P.chain_(fa, (a) => O.getOrElse_(pf(a), () => P.fail(e)))
}
exports.continueOrFailM_ = continueOrFailM_
/**
 * Fail with `e` if the supplied `PartialFunction` does not match, otherwise
 * continue with the returned value.
 *
 * @dataFirst continueOrFailM_
 */
function continueOrFailM(e, pf) {
  return (fa) => continueOrFailM_(fa, e, pf)
}
exports.continueOrFailM = continueOrFailM
/**
 * Fail with `e` if the supplied `PartialFunction` does not match, otherwise
 * succeed with the returned value.
 */
function continueOrFail_(fa, e, pf) {
  return continueOrFailM_(fa, e, (x) => O.map_(pf(x), P.succeed))
}
exports.continueOrFail_ = continueOrFail_
/**
 * Fail with `e` if the supplied `PartialFunction` does not match, otherwise
 * succeed with the returned value.
 *
 * @dataFirst continueOrFail_
 */
function continueOrFail(e, pf) {
  return (fa) => continueOrFail_(fa, e, pf)
}
exports.continueOrFail = continueOrFail
/**
 * Fail with `e` if the supplied `PartialFunction` does not match, otherwise
 * continue with the returned value.
 */
function continueOrFailWithM_(fa, e, pf) {
  return P.chain_(fa, (a) => O.getOrElse_(pf(a), () => P.failWith(e)))
}
exports.continueOrFailWithM_ = continueOrFailWithM_
/**
 * Fail with `e` if the supplied `PartialFunction` does not match, otherwise
 * continue with the returned value.
 *
 * @dataFirst continueOrFailWithM_
 */
function continueOrFailWithM(e, pf) {
  return (fa) => continueOrFailWithM_(fa, e, pf)
}
exports.continueOrFailWithM = continueOrFailWithM
/**
 * Fail with `e` if the supplied `PartialFunction` does not match, otherwise
 * succeed with the returned value.
 */
function continueOrFailWith_(fa, e, pf) {
  return continueOrFailWithM_(fa, e, (x) => O.map_(pf(x), P.succeed))
}
exports.continueOrFailWith_ = continueOrFailWith_
/**
 * Fail with `e` if the supplied `PartialFunction` does not match, otherwise
 * succeed with the returned value.
 *
 * @dataFirst continueOrFailWith_
 */
function continueOrFailWith(e, pf) {
  return (fa) => continueOrFailWith_(fa, e, pf)
}
exports.continueOrFailWith = continueOrFailWith
/**
 * Creates a composite effect that represents this effect followed by another
 * one that may depend on the error produced by this one.
 *
 * @dataFirst chainError_
 */
function chainError(f) {
  return (self) => chainError_(self, f)
}
exports.chainError = chainError
/**
 * Creates a composite effect that represents this effect followed by another
 * one that may depend on the error produced by this one.
 */
function chainError_(self, f) {
  return flipWith_(self, (x) => P.chain_(x, f))
}
exports.chainError_ = chainError_
/**
 * Checks the condition, and if it's true, returns unit, otherwise, retries.
 */
function checkWith(predicate) {
  return suspend(() => (predicate() ? P.unit : P.retry))
}
exports.checkWith = checkWith
/**
 * Checks the condition, and if it's true, returns unit, otherwise, retries.
 */
function check(predicate) {
  return checkWith(() => predicate)
}
exports.check = check
/**
 * Propagates self environment to that.
 */
function compose_(self, that) {
  return andThen_(that, self)
}
exports.compose_ = compose_
/**
 * Propagates self environment to that.
 *
 * @dataFirst compose_
 */
function compose(that) {
  return (self) => andThen_(that, self)
}
exports.compose = compose
/**
 * Commits this transaction atomically.
 */
function commit(self) {
  return T.accessM((r) =>
    T.suspend((_, fiberId) => {
      const v = (0, Journal_1.tryCommit)(fiberId, self, r)
      switch (v._typeId) {
        case TryCommit_1.DoneTypeId: {
          return v.io
        }
        case TryCommit_1.SuspendTypeId: {
          const txnId = (0, TxnId_1.makeTxnId)()
          const done = new AtomicBoolean_1.AtomicBoolean(false)
          const interrupt = T.succeedWith(() => done.set(true))
          const io = T.effectAsync(
            (0, Journal_1.tryCommitAsync)(v.journal, fiberId, self, txnId, done, r)
          )
          return T.ensuring_(io, interrupt)
        }
      }
    })
  )
}
exports.commit = commit
/**
 * Commits this transaction atomically, regardless of whether the transaction
 * is a success or a failure.
 */
function commitEither(self) {
  return T.absolve(commit(either(self)))
}
exports.commitEither = commitEither
/**
 * Kills the fiber running the effect with a `RuntimeError` that contains
 * the specified message.
 */
function dieMessage(message) {
  return P.dieWith(() => new Cause_1.RuntimeError(message))
}
exports.dieMessage = dieMessage
/**
 * Kills the fiber running the effect with a `RuntimeError` that contains
 * the specified message.
 */
function dieMessageWith(message) {
  return P.succeedWith(() => {
    throw new Cause_1.RuntimeError(message())
  })
}
exports.dieMessageWith = dieMessageWith
/**
 * Converts the failure channel into an `Either`.
 */
function either(self) {
  return fold_(
    self,
    (x) => E.left(x),
    (x) => E.right(x)
  )
}
exports.either = either
/**
 * Retrieves the environment inside an stm.
 */
function environment() {
  return new P.STMEffect((_, __, r) => r)
}
exports.environment = environment
/**
 * Returns an effect that ignores errors and runs repeatedly until it eventually succeeds.
 */
function eventually(self) {
  return P.foldM_(self, () => eventually(self), P.succeed)
}
exports.eventually = eventually
function filterOrDie(p, dieWith) {
  return (fa) => filterOrDie_(fa, p, dieWith)
}
exports.filterOrDie = filterOrDie
function filterOrDie_(fa, p, dieWith) {
  return filterOrElse_(fa, p, (x) => P.dieWith(() => dieWith(x)))
}
exports.filterOrDie_ = filterOrDie_
function filterOrFail(p, failWith) {
  return (fa) => filterOrFail_(fa, p, failWith)
}
exports.filterOrFail = filterOrFail
function filterOrFail_(fa, p, failWith) {
  return filterOrElse_(fa, p, (x) => fail(failWith(x)))
}
exports.filterOrFail_ = filterOrFail_
function filterOrElse(p, or) {
  return (fa) => filterOrElse_(fa, p, or)
}
exports.filterOrElse = filterOrElse
function filterOrElse_(fa, p, or) {
  return P.chain_(fa, (a) => (p(a) ? P.succeed(a) : suspend(() => or(a))))
}
exports.filterOrElse_ = filterOrElse_
function filterOrDieMessage(p, message) {
  return (fa) => filterOrDieMessage_(fa, p, message)
}
exports.filterOrDieMessage = filterOrDieMessage
function filterOrDieMessage_(fa, p, message) {
  return filterOrDie_(fa, p, (a) => new Cause_1.RuntimeError(message(a)))
}
exports.filterOrDieMessage_ = filterOrDieMessage_
/**
 * Returns an effect that swaps the error/success cases. This allows you to
 * use all methods on the error channel, possibly before flipping back.
 */
function flip(self) {
  return P.foldM_(self, P.succeed, P.fail)
}
exports.flip = flip
/**
 * Swaps the error/value parameters, applies the function `f` and flips the parameters back
 *
 * @dataFirst flipWith_
 */
function flipWith(f) {
  return (self) => flipWith_(self, f)
}
exports.flipWith = flipWith
/**
 * Swaps the error/value parameters, applies the function `f` and flips the parameters back
 */
function flipWith_(self, f) {
  return flip(f(flip(self)))
}
exports.flipWith_ = flipWith_
/**
 * Folds over the `STM` effect, handling both P.failure and success, but not
 * retry.
 */
function fold_(self, g, f) {
  return P.foldM_(
    self,
    (e) => P.succeed(g(e)),
    (a) => P.succeed(f(a))
  )
}
exports.fold_ = fold_
/**
 * Folds over the `STM` effect, handling both P.failure and success, but not
 * retry.
 *
 * @dataFirst fold_
 */
function fold(g, f) {
  return (self) => fold_(self, g, f)
}
exports.fold = fold
/**
 * Flattens out a nested `STM` effect.
 */
function flatten(self) {
  return P.chain_(self, Function_1.identity)
}
exports.flatten = flatten
/**
 * Unwraps the optional error, defaulting to the provided value.
 *
 * @dataFirst flattenErrorOptionWith_
 */
function flattenErrorOptionWith(def) {
  return (self) => flattenErrorOptionWith_(self, def)
}
exports.flattenErrorOptionWith = flattenErrorOptionWith
/**
 * Unwraps the optional error, defaulting to the provided value.
 */
function flattenErrorOptionWith_(self, def) {
  return mapError_(self, O.fold(def, Function_1.identity))
}
exports.flattenErrorOptionWith_ = flattenErrorOptionWith_
/**
 * Unwraps the optional error, defaulting to the provided value.
 *
 * @dataFirst flattenErrorOption_
 */
function flattenErrorOption(def) {
  return (self) => flattenErrorOption_(self, def)
}
exports.flattenErrorOption = flattenErrorOption
/**
 * Unwraps the optional error, defaulting to the provided value.
 */
function flattenErrorOption_(self, def) {
  return mapError_(
    self,
    O.fold(() => def, Function_1.identity)
  )
}
exports.flattenErrorOption_ = flattenErrorOption_
/**
 * Applies the function `f` to each element of the `Iterable<A>` and
 * returns a transactional effect that produces a new `ReadonlyArray<B>`.
 */
function forEach_(it, f) {
  return suspend(() => {
    let stm = P.succeed([])
    for (const a of it) {
      stm = zipWith_(stm, f(a), (acc, b) => {
        acc.push(b)
        return acc
      })
    }
    return stm
  })
}
exports.forEach_ = forEach_
/**
 * Applies the function `f` to each element of the `Iterable<A>` and
 * returns a transactional effect that produces a new `ReadonlyArray<B>`.
 *
 * @dataFirst forEach_
 */
function forEach(f) {
  return (self) => forEach_(self, f)
}
exports.forEach = forEach
/**
 * Lifts an `Either` into a `STM`.
 */
function fromEitherWith(e) {
  return suspend(() => {
    return E.fold_(e(), P.fail, P.succeed)
  })
}
exports.fromEitherWith = fromEitherWith
/**
 * Lifts an `Either` into a `STM`.
 */
function fromEither(e) {
  return E.fold_(e, P.fail, P.succeed)
}
exports.fromEither = fromEither
/**
 * Unwraps the optional success of this effect, but can fail with an None value.
 */
function get(self) {
  return P.foldM_(
    self,
    (x) => P.fail(O.some(x)),
    O.fold(() => P.fail(O.none), P.succeed)
  )
}
exports.get = get
/**
 * Returns a successful effect with the head of the list if the list is
 * non-empty or fails with the error `None` if the list is empty.
 */
function head(self) {
  return P.foldM_(
    self,
    (x) => P.fail(O.some(x)),
    (x) => {
      const it = x[Symbol.iterator]()
      const next = it.next()
      return next.done ? P.fail(O.none) : P.succeed(next.value)
    }
  )
}
exports.head = head
/**
 * Returns a new effect that ignores the success or failure of this effect.
 */
function ignore(self) {
  return fold_(self, Function_1.constVoid, Function_1.constVoid)
}
exports.ignore = ignore
/**
 * Returns whether this effect is a failure.
 */
function isFailure(self) {
  return fold_(
    self,
    () => true,
    () => false
  )
}
exports.isFailure = isFailure
/**
 * Returns whether this effect is a success.
 */
function isSuccess(self) {
  return fold_(
    self,
    () => false,
    () => true
  )
}
exports.isSuccess = isSuccess
/**
 * Returns a successful effect if the value is `Left`, or fails with the error `None`.
 */
function left(self) {
  return P.foldM_(
    self,
    (e) => P.fail(O.some(e)),
    E.fold(P.succeed, () => P.fail(O.none))
  )
}
exports.left = left
/**
 * Returns a successful effect if the value is `Left`, or fails with the error e.
 */
function leftOrFail_(self, orFail) {
  return P.chain_(
    self,
    E.fold(P.succeed, (x) => P.failWith(() => orFail(x)))
  )
}
exports.leftOrFail_ = leftOrFail_
/**
 * Returns a successful effect if the value is `Left`, or fails with the error e.
 *
 * @dataFirst leftOrFail_
 */
function leftOrFail(orFail) {
  return (self) => leftOrFail_(self, orFail)
}
exports.leftOrFail = leftOrFail
/**
 * Returns a successful effect if the value is `Left`, or fails with a `NoSuchElementException`.
 */
function leftOrFailException(self) {
  return leftOrFail_(self, () => new GlobalExceptions_1.NoSuchElementException())
}
exports.leftOrFailException = leftOrFailException
/**
 * Depending on provided environment returns either this one or the other effect.
 *
 * @dataFirst join_
 */
function join(that) {
  return (self) => {
    return join_(self, that)
  }
}
exports.join = join
/**
 * Depending on provided environment returns either this one or the other effect.
 */
function join_(self, that) {
  return accessM((_) =>
    E.fold_(
      _,
      (r) => provideAll_(self, r),
      (r1) => provideAll_(that, r1)
    )
  )
}
exports.join_ = join_
/**
 * Depending on provided environment returns either this one or the other effect.
 */
function joinEither_(self, that) {
  return accessM((_) =>
    E.fold_(
      _,
      (r) => P.map_(provideAll_(self, r), E.left),
      (r1) => P.map_(provideAll_(that, r1), E.right)
    )
  )
}
exports.joinEither_ = joinEither_
/**
 * Depending on provided environment returns either this one or the other effect.
 */
function joinEither(that) {
  return (self) => joinEither_(self, that)
}
exports.joinEither = joinEither
/**
 * Maps from one error type to another.
 */
function mapError_(self, f) {
  return P.foldM_(self, (e) => P.fail(f(e)), P.succeed)
}
exports.mapError_ = mapError_
/**
 * Maps from one error type to another.
 *
 * @dataFirst mapError_
 */
function mapError(f) {
  return (self) => mapError_(self, f)
}
exports.mapError = mapError
/**
 * Provides the transaction its required environment, which eliminates
 * its dependency on `R`.
 */
function provideAll_(self, r) {
  return P.provideSome_(self, () => r)
}
exports.provideAll_ = provideAll_
/**
 * Provides the transaction its required environment, which eliminates
 * its dependency on `R`.
 *
 * @dataFirst provideAll_
 */
function provideAll(r) {
  return (self) => provideAll_(self, r)
}
exports.provideAll = provideAll
/**
 * Repeats this `STM` effect until its result satisfies the specified predicate.
 *
 * WARNING:
 * `repeatUntil` uses a busy loop to repeat the effect and will consume a thread until
 * it completes (it cannot yield). This is because STM describes a single atomic
 * transaction which must either complete, retry or fail a transaction before
 * yielding back to the Effect Runtime.
 *
 * - Use `retryUntil` instead if you don't need to maintain transaction state for repeats.
 * - Ensure repeating the STM effect will eventually satisfy the predicate.
 */
function repeatUntil_(self, f) {
  return P.chain_(self, (a) => (f(a) ? P.succeed(a) : repeatUntil_(self, f)))
}
exports.repeatUntil_ = repeatUntil_
/**
 * Repeats this `STM` effect until its result satisfies the specified predicate.
 *
 * WARNING:
 * `repeatUntil` uses a busy loop to repeat the effect and will consume a thread until
 * it completes (it cannot yield). This is because STM describes a single atomic
 * transaction which must either complete, retry or fail a transaction before
 * yielding back to the Effect Runtime.
 *
 * - Use `retryUntil` instead if you don't need to maintain transaction state for repeats.
 * - Ensure repeating the STM effect will eventually satisfy the predicate.
 *
 * @dataFirst repeatUntil_
 */
function repeatUntil(f) {
  return (self) => repeatUntil_(self, f)
}
exports.repeatUntil = repeatUntil
/**
 * Repeats this `STM` effect while its result satisfies the specified predicate.
 *
 * WARNING:
 * `repeatWhile` uses a busy loop to repeat the effect and will consume a thread until
 * it completes (it cannot yield). This is because STM describes a single atomic
 * transaction which must either complete, retry or fail a transaction before
 * yielding back to the Effect Runtime.
 *
 * - Use `retryWhile` instead if you don't need to maintain transaction state for repeats.
 * - Ensure repeating the STM effect will eventually not satisfy the predicate.
 */
function repeatWhile_(self, f) {
  return P.chain_(self, (a) => (f(a) ? repeatWhile_(self, f) : P.succeed(a)))
}
exports.repeatWhile_ = repeatWhile_
/**
 * Repeats this `STM` effect while its result satisfies the specified predicate.
 *
 * WARNING:
 * `repeatWhile` uses a busy loop to repeat the effect and will consume a thread until
 * it completes (it cannot yield). This is because STM describes a single atomic
 * transaction which must either complete, retry or fail a transaction before
 * yielding back to the Effect Runtime.
 *
 * - Use `retryWhile` instead if you don't need to maintain transaction state for repeats.
 * - Ensure repeating the STM effect will eventually not satisfy the predicate.
 *
 * @dataFirst repeatWhile_
 */
function repeatWhile(f) {
  return (self) => repeatWhile_(self, f)
}
exports.repeatWhile = repeatWhile
/**
 * Suspends creation of the specified transaction lazily.
 */
function suspend(f) {
  return flatten(P.succeedWith(f))
}
exports.suspend = suspend
/**
 * "Peeks" at the success of transactional effect.
 */
function tap_(self, f) {
  return P.chain_(self, (a) => as_(f(a), a))
}
exports.tap_ = tap_
/**
 * "Peeks" at the success of transactional effect.
 *
 * @dataFirst tap_
 */
function tap(f) {
  return (self) => tap_(self, f)
}
exports.tap = tap
/**
 * Returns an effect with the value on the left part.
 */
function toLeftWith(a) {
  return P.chain_(P.succeedWith(a), (x) => P.succeed(E.left(x)))
}
exports.toLeftWith = toLeftWith
/**
 * Returns an effect with the value on the left part.
 */
function toLeft(a) {
  return P.succeed(E.left(a))
}
exports.toLeft = toLeft
/**
 * Sequentially zips this value with the specified one, combining the values
 * using the specified combiner function.
 */
function zipWith_(self, that, f) {
  return P.chain_(self, (a) => P.map_(that, (b) => f(a, b)))
}
exports.zipWith_ = zipWith_
/**
 * Sequentially zips this value with the specified one, combining the values
 * using the specified combiner function.
 *
 * @dataFirst zipWith_
 */
function zipWith(that, f) {
  return (self) => P.chain_(self, (a) => P.map_(that, (b) => f(a, b)))
}
exports.zipWith = zipWith
//# sourceMappingURL=core.js.map
