@effect-ts/system
Version:
Effect-TS is a zero dependency set of libraries to write highly productive, purely functional TypeScript at scale.
1,828 lines (1,690 loc) • 83 kB
text/typescript
// ets_tracing: off
import type { Cause } from "../../Cause/index.js"
import * as C from "../../Cause/index.js"
import { RuntimeError } from "../../Cause/index.js"
import type { HasClock } from "../../Clock/index.js"
import * as A from "../../Collections/Immutable/Array/index.js"
import * as Chunk from "../../Collections/Immutable/Chunk/index.js"
import * as R from "../../Collections/Immutable/Dictionary/index.js"
import * as NA from "../../Collections/Immutable/NonEmptyArray/index.js"
import * as SS from "../../Collections/Immutable/SortedSet/index.js"
import * as Tp from "../../Collections/Immutable/Tuple/index.js"
import type { Effect } from "../../Effect/index.js"
import * as T from "../../Effect/index.js"
import { ITracer } from "../../Effect/primitives.js"
import * as E from "../../Either/index.js"
import * as Ex from "../../Exit/index.js"
import type { FiberID } from "../../Fiber/index.js"
import * as F from "../../Fiber/index.js"
import { constVoid, identity, pipe } from "../../Function/index.js"
import { NoSuchElementException } from "../../GlobalExceptions/index.js"
import type { Has, Tag } from "../../Has/index.js"
import { mergeEnvironments } from "../../Has/index.js"
import * as I from "../../Iterable/index.js"
import * as L from "../../Layer/index.js"
import type { Option } from "../../Option/index.js"
import * as O from "../../Option/index.js"
import * as P from "../../Promise/index.js"
import type { Schedule } from "../../Schedule/index.js"
import { track } from "../../Supervisor/index.js"
import type { UnionToIntersection } from "../../Utils/index.js"
import * as core from "../core.js"
import * as forEach from "../forEach.js"
import { fromEffect } from "../fromEffect.js"
import { makeExit_ } from "../makeExit.js"
import type { IO, Managed, RIO, UIO } from "../managed.js"
import { managedApply } from "../managed.js"
import * as add from "../ReleaseMap/add.js"
import type * as RM from "../ReleaseMap/index.js"
import * as makeReleaseMap from "../ReleaseMap/makeReleaseMap.js"
import * as releaseAll from "../ReleaseMap/releaseAll.js"
import { succeed } from "../succeed.js"
import { absolve } from "./absolve.js"
import { environment } from "./environment.js"
import { foldM_ } from "./foldM.js"
import { halt } from "./halt.js"
import { releaseMap } from "./releaseMap.js"
import { suspend } from "./suspend.js"
/**
* Attempts to convert defects into a failure, throwing away all information
* about the cause of the failure.
*
* @ets_data_first absorb_
*/
export function absorb<E>(f: (e: E) => unknown, __trace?: string) {
return <R, A>(self: Managed<R, E, A>) => absorb_(self, f, __trace)
}
/**
* Attempts to convert defects into a failure, throwing away all information
* about the cause of the failure.
*/
export function absorb_<R, A, E>(
self: Managed<R, E, A>,
f: (e: E) => unknown,
__trace?: string
) {
return foldM_(sandbox(self), (c) => core.fail(C.squash(f)(c)), succeed, __trace)
}
/**
* Unwraps the optional success of this effect, but can fail with None value.
*/
export function get<R, A>(self: Managed<R, never, O.Option<A>>, __trace?: string) {
return absolve(
core.map_(
self,
E.fromOption(() => O.none)
),
__trace
)
}
/**
* Returns an effect whose failure is mapped by the specified `f` function.
*/
export function mapError_<R, A, E, E2>(
self: Managed<R, E, A>,
f: (e: E) => E2,
__trace?: string
) {
return managedApply(T.mapError_(self.effect, f, __trace))
}
/**
* Returns an effect whose failure is mapped by the specified `f` function.
*
* @ets_data_first mapError_
*/
export function mapError<E, E2>(f: (e: E) => E2, __trace?: string) {
return <R, A>(self: Managed<R, E, A>) => mapError_(self, f, __trace)
}
/**
* Returns an effect whose full failure is mapped by the specified `f` function.
*/
export function mapErrorCause_<R, A, E, E2>(
self: Managed<R, E, A>,
f: (e: C.Cause<E>) => C.Cause<E2>,
__trace?: string
) {
return managedApply(T.mapErrorCause_(self.effect, f, __trace))
}
/**
* Returns an effect whose full failure is mapped by the specified `f` function.
*
* @ets_data_first mapErrorCause_
*/
export function mapErrorCause<E, E2>(
f: (e: C.Cause<E>) => C.Cause<E2>,
__trace?: string
) {
return <R, A>(self: Managed<R, E, A>) => mapErrorCause_(self, f, __trace)
}
/**
* Returns a memoized version of the specified managed.
*/
export function memoize<R, E, A>(
self: Managed<R, E, A>,
__trace?: string
): UIO<Managed<R, E, A>> {
return core.mapM_(
releaseMap,
(finalizers) =>
pipe(
T.do,
T.bind("promise", () => P.make<E, A>()),
T.bind("complete", ({ promise }) =>
T.once(
T.accessM((r: R) =>
pipe(
self.effect,
T.provideAll(Tp.tuple(r, finalizers)),
T.map((_) => _.get(1)),
T.to(promise)
)
)
)
),
T.map(({ complete, promise }) =>
pipe(complete, T.zipRight(P.await(promise)), T.toManaged)
)
),
__trace
)
}
/**
* Returns a new effect where the error channel has been merged into the
* success channel to their common combined type.
*/
export function merge<R, E, A>(self: Managed<R, E, A>, __trace?: string) {
return foldM_(self, succeed, succeed, __trace)
}
/**
* Returns the managed resulting from mapping the success of this managed to unit.
*/
export const unit = suspend(() => fromEffect(T.unit))
/**
* Requires the option produced by this value to be `None`.
*/
export function none<R, E, A>(
self: Managed<R, E, O.Option<A>>,
__trace?: string
): Managed<R, O.Option<E>, void> {
return foldM_(
self,
(x) => pipe(x, O.some, core.fail),
O.fold(
() => unit,
() => core.fail(O.none)
),
__trace
)
}
/**
* Folds over the failure value or the success value to yield an effect that
* does not fail, but succeeds with the value returned by the left or right
* function passed to `fold`.
*/
export function fold_<R, E, A, B, C>(
self: Managed<R, E, A>,
onFail: (e: E) => B,
onSuccess: (a: A) => C,
__trace?: string
) {
return foldM_(
self,
(x) => pipe(x, onFail, succeed),
(x) => pipe(x, onSuccess, succeed),
__trace
)
}
/**
* Folds over the failure value or the success value to yield an effect that
* does not fail, but succeeds with the value returned by the left or right
* function passed to `fold`.
*
* @ets_data_first fold_
*/
export function fold<E, A, B, C>(
onFail: (e: E) => B,
onSuccess: (a: A) => C,
__trace?: string
) {
return <R>(self: Managed<R, E, A>) => fold_(self, onFail, onSuccess, __trace)
}
/**
* Executes this effect, skipping the error but returning optionally the success.
*/
export function option<R, E, A>(
self: Managed<R, E, A>,
__trace?: string
): Managed<R, never, O.Option<A>> {
return fold_(self, () => O.none, O.some, __trace)
}
/**
* Converts an option on errors into an option on values.
*/
export function optional<R, E, A>(
self: Managed<R, O.Option<E>, A>,
__trace?: string
): Managed<R, E, O.Option<A>> {
return foldM_(
self,
O.fold(() => succeed(O.none), core.fail),
(x) => pipe(x, O.some, succeed),
__trace
)
}
/**
* Keeps none of the errors, and terminates the fiber with them, using
* the specified function to convert the `E` into a `Throwable`.
*
* @ets_data_first orDieWith_
*/
export function orDieWith<E>(f: (e: E) => unknown, __trace?: string) {
return <R, A>(self: Managed<R, E, A>) => orDieWith_(self, f, __trace)
}
/**
* Keeps none of the errors, and terminates the fiber with them, using
* the specified function to convert the `E` into a `Throwable`.
*/
export function orDieWith_<R, E, A>(
self: Managed<R, E, A>,
f: (e: E) => unknown,
__trace?: string
) {
return managedApply(T.orDieWith_(self.effect, f, __trace))
}
/**
* Translates effect failure into death of the fiber, making all failures unchecked and
* not a part of the type of the effect.
*/
export function orDie<R, E, A>(self: Managed<R, E, A>, __trace?: string) {
return orDieWith_(self, identity, __trace)
}
/**
* Executes this effect and returns its value, if it succeeds, but
* otherwise executes the specified effect.
*
* @ets_data_first orElse_
*/
export function orElse<R2, E2, A2>(that: () => Managed<R2, E2, A2>, __trace?: string) {
return <R, E, A>(self: Managed<R, E, A>) => orElse_(self, that, __trace)
}
/**
* Executes this effect and returns its value, if it succeeds, but
* otherwise executes the specified effect.
*/
export function orElse_<R, E, A, R2, E2, A2>(
self: Managed<R, E, A>,
that: () => Managed<R2, E2, A2>,
__trace?: string
) {
return foldM_(self, () => that(), succeed, __trace)
}
/**
* Executes this effect and returns its value, if it succeeds, but
* otherwise fails with the specified error.
*
* @ets_data_first orElseFail_
*/
export function orElseFail<E2>(e: E2, __trace?: string) {
return <R, E, A>(self: Managed<R, E, A>) => orElseFail_(self, e, __trace)
}
/**
* Executes this effect and returns its value, if it succeeds, but
* otherwise fails with the specified error.
*/
export function orElseFail_<R, E, A, E2>(
self: Managed<R, E, A>,
e: E2,
__trace?: string
) {
return orElse_(self, () => core.fail(e), __trace)
}
/**
* Executes this effect and returns its value, if it succeeds, but
* otherwise executes the specified effect.
*
* @ets_data_first orElseEither_
*/
export function orElseEither<R2, E2, A2>(
that: () => Managed<R2, E2, A2>,
__trace?: string
) {
return <R, E, A>(self: Managed<R, E, A>): Managed<R & R2, E2, E.Either<A2, A>> =>
orElseEither_(self, that, __trace)
}
/**
* Executes this effect and returns its value, if it succeeds, but
* otherwise executes the specified effect.
*/
export function orElseEither_<R, E, A, R2, E2, A2>(
self: Managed<R, E, A>,
that: () => Managed<R2, E2, A2>,
__trace?: string
): Managed<R & R2, E2, E.Either<A2, A>> {
return foldM_(
self,
() => core.map_(that(), E.left),
(x) => pipe(x, E.right, succeed),
__trace
)
}
/**
* Returns an effect that will produce the value of this effect, unless it
* fails with the `None` value, in which case it will produce the value of
* the specified effect.
*/
export function orElseOptional_<R, E, A, R2, E2, A2>(
self: Managed<R, O.Option<E>, A>,
that: () => Managed<R2, O.Option<E2>, A2>,
__trace?: string
): Managed<R & R2, O.Option<E | E2>, A | A2> {
return catchAll_(
self,
O.fold(
() => that(),
(e) => core.fail(O.some<E | E2>(e))
),
__trace
)
}
/**
* Returns an effect that will produce the value of this effect, unless it
* fails with the `None` value, in which case it will produce the value of
* the specified effect.
*
* @ets_data_first orElseOptional_
*/
export function orElseOptional<R2, E2, A2>(
that: () => Managed<R2, O.Option<E2>, A2>,
__trace?: string
) {
return <R, E, A>(self: Managed<R, O.Option<E>, A>) =>
orElseOptional_(self, that, __trace)
}
/**
* Executes this effect and returns its value, if it succeeds, but
* otherwise succeeds with the specified value.
*/
export function orElseSucceed_<R, E, A, A2>(
self: Managed<R, O.Option<E>, A>,
that: () => A2,
__trace?: string
): Managed<R, O.Option<E>, A | A2> {
return orElse_(self, () => succeed(that()), __trace)
}
/**
* Executes this effect and returns its value, if it succeeds, but
* otherwise succeeds with the specified value.
*
* @ets_data_first orElseSucceed_
*/
export function orElseSucceed<R, E, A, A2>(that: () => A2, __trace?: string) {
return (self: Managed<R, O.Option<E>, A>) => orElseSucceed_(self, that, __trace)
}
/**
* Recovers from all errors.
*/
export function catchAll_<R, E, A, R2, E2, A2>(
self: Managed<R, E, A>,
f: (e: E) => Managed<R2, E2, A2>,
__trace?: string
) {
return foldM_(self, f, succeed, __trace)
}
/**
* Recovers from all errors.
*
* @ets_data_first catchAll_
*/
export function catchAll<E, R2, E2, A2>(
f: (e: E) => Managed<R2, E2, A2>,
__trace?: string
) {
return <R, A>(self: Managed<R, E, A>) => catchAll_(self, f, __trace)
}
/**
* Recovers from all errors with provided Cause.
*/
export function catchAllCause_<R, E, A, R2, E2, A2>(
self: Managed<R, E, A>,
f: (e: C.Cause<E>) => Managed<R2, E2, A2>,
__trace?: string
) {
return core.foldCauseM_(self, f, succeed, __trace)
}
/**
* Recovers from all errors with provided Cause.
*
* @ets_data_first catchAllCause_
*/
export function catchAllCause<E, R2, E2, A2>(
f: (e: C.Cause<E>) => Managed<R2, E2, A2>,
__trace?: string
) {
return <R, A>(self: Managed<R, E, A>) => core.foldCauseM_(self, f, succeed, __trace)
}
/**
* Recovers from some or all of the error cases.
*/
export function catchSome_<R, E, A, R2, E2, A2>(
self: Managed<R, E, A>,
pf: (e: E) => O.Option<Managed<R2, E2, A2>>,
__trace?: string
): Managed<R & R2, E | E2, A | A2> {
return catchAll_(
self,
(e) => O.getOrElse_(pf(e), () => core.fail<E | E2>(e)),
__trace
)
}
/**
* Recovers from some or all of the error cases.
*
* @ets_data_first catchSome_
*/
export function catchSome<E, R2, E2, A2>(
pf: (e: E) => O.Option<Managed<R2, E2, A2>>,
__trace?: string
) {
return <R, A>(self: Managed<R, E, A>) => catchSome_(self, pf, __trace)
}
/**
* Recovers from some or all of the error cases.
*/
export function catchSomeCause_<R, E, A, R2, E2, A2>(
self: Managed<R, E, A>,
pf: (e: C.Cause<E>) => O.Option<Managed<R2, E2, A2>>,
__trace?: string
): Managed<R & R2, E | E2, A | A2> {
return catchAllCause_(
self,
(e) => O.getOrElse_(pf(e), () => halt<E | E2>(e)),
__trace
)
}
/**
* Recovers from some or all of the error cases.
*
* @ets_data_first catchSomeCause_
*/
export function catchSomeCause<R, E, A, R2, E2, A2>(
pf: (e: C.Cause<E>) => O.Option<Managed<R2, E2, A2>>,
__trace?: string
) {
return (self: Managed<R, E, A>) => catchSomeCause_(self, pf, __trace)
}
/**
* Fail with `e` if the supplied `PartialFunction` does not match, otherwise
* continue with the returned value.
*/
export function continueOrFailM_<R, E, A, E1, R1, E2, B>(
self: Managed<R, E, A>,
e: () => E1,
pf: (a: A) => O.Option<Managed<R1, E2, B>>,
__trace?: string
): Managed<R & R1, E | E1 | E2, B> {
return core.chain_(
self,
(a) => O.getOrElse_(pf(a), () => core.fail<E1 | E2>(e())),
__trace
)
}
/**
* Fail with `e` if the supplied `PartialFunction` does not match, otherwise
* continue with the returned value.
*
* @ets_data_first continueOrFailM_
*/
export function continueOrFailM<A, E1, R1, E2, B>(
e: () => E1,
pf: (a: A) => O.Option<Managed<R1, E2, B>>,
__trace?: string
) {
return <R, E>(self: Managed<R, E, A>) => continueOrFailM_(self, e, pf, __trace)
}
/**
* Fail with `e` if the supplied `PartialFunction` does not match, otherwise
* succeed with the returned value.
*/
export function continueOrFail_<R, E, A, E1, B>(
self: Managed<R, E, A>,
e: () => E1,
pf: (a: A) => O.Option<B>,
__trace?: string
): Managed<R, E | E1, B> {
return continueOrFailM_(self, e, (x) => pipe(x, pf, O.map(succeed)), __trace)
}
/**
* Fail with `e` if the supplied `PartialFunction` does not match, otherwise
* succeed with the returned value.
*
* @ets_data_first continueOrFail_
*/
export function continueOrFail<A, E1, B>(
e: () => E1,
pf: (a: A) => O.Option<B>,
__trace?: string
) {
return <R, E>(self: Managed<R, E, A>) => continueOrFail_(self, e, pf, __trace)
}
/**
* Provides some of the environment required to run this effect,
* leaving the remainder `R0` and combining it automatically using spread.
*/
export function provide<R>(r: R, __trace?: string) {
return <E, A, R0>(next: Managed<R & R0, E, A>): Managed<R0, E, A> =>
core.provideSome_(next, (r0: R0) => ({ ...r0, ...r }), __trace)
}
/**
* Executes the second effect and then provides its output as an environment to this effect
*
* @ets_data_first compose_
*/
export function compose<A, E2, B>(that: Managed<A, E2, B>, __trace?: string) {
return <R, E>(self: Managed<R, E, A>) => compose_(self, that, __trace)
}
/**
* Executes the second effect and then provides its output as an environment to this effect
*/
export function compose_<R, E, A, E2, B>(
self: Managed<R, E, A>,
that: Managed<A, E2, B>,
__trace?: string
) {
return pipe(
environment<R>(),
core.chain((r1) =>
pipe(
core.provideAll_(self, r1),
core.chain((r) => core.provideAll_(that, r))
)
)
)
}
/**
* Returns an effect whose failure and success have been lifted into an
* `Either`. The resulting effect cannot fail
*/
export function either<R, E, A>(
self: Managed<R, E, A>,
__trace?: string
): Managed<R, never, E.Either<E, A>> {
return fold_(self, E.left, E.right, __trace)
}
/**
* Returns a Managed that ignores errors raised by the acquire effect and
* runs it repeatedly until it eventually succeeds.
*/
export function eventually<R, E, A>(
self: Managed<R, E, A>,
__trace?: string
): Managed<R, never, A> {
return managedApply(T.eventually(self.effect, __trace))
}
/**
* Zips this effect with its environment
*/
export function first<R, E, A>(self: Managed<R, E, A>, __trace?: string) {
return core.zip_(self, environment<R>(), __trace)
}
/**
* Effectfully map the error channel
*/
export function chainError_<R, E, A, R2, E2>(
self: Managed<R, E, A>,
f: (e: E) => RIO<R2, E2>,
__trace?: string
): Managed<R & R2, E2, A> {
return flipWith_(self, core.chain(f, __trace))
}
/**
* Effectfully map the error channel
*
* @ets_data_first chainError_
*/
export function chainError<E, R2, E2>(f: (e: E) => RIO<R2, E2>, __trace?: string) {
return <R, A>(self: Managed<R, E, A>) => chainError_(self, f, __trace)
}
/**
* Flip the error and result
*/
export function flip<R, E, A>(
self: Managed<R, E, A>,
__trace?: string
): Managed<R, A, E> {
return foldM_(self, succeed, core.fail, __trace)
}
/**
* Flip the error and result, then apply an effectful function to the effect
*/
export function flipWith_<R, E, A, R2, E1, A1>(
self: Managed<R, E, A>,
f: (_: Managed<R, A, E>) => Managed<R2, A1, E1>,
__trace?: string
) {
return flip(f(flip(self)), __trace)
}
/**
* Flip the error and result, then apply an effectful function to the effect
*
* @ets_data_first flipWith_
*/
export function flipWith<R, E, A, R2, E1, A1>(
f: (_: Managed<R, A, E>) => Managed<R2, A1, E1>,
__trace?: string
) {
return (self: Managed<R, E, A>) => flipWith_(self, f, __trace)
}
/**
* Returns an effect that performs the outer effect first, followed by the
* inner effect, yielding the value of the inner effect.
*
* This method can be used to "flatten" nested effects.
*/
export function flatten<R2, E2, R, E, A>(
self: Managed<R2, E2, Managed<R, E, A>>,
__trace?: string
) {
return core.chain_(self, identity, __trace)
}
/**
* Returns an effect that performs the outer effect first, followed by the
* inner effect, yielding the value of the inner effect.
*
* This method can be used to "flatten" nested effects.
*/
export function flattenM<R2, E2, R, E, A>(
self: Managed<R2, E2, T.Effect<R, E, A>>,
__trace?: string
) {
return core.mapM_(self, identity, __trace)
}
/**
* A more powerful version of `fold` that allows recovering from any kind of failure except interruptions.
*/
export function foldCause_<R, E, A, B, C>(
self: Managed<R, E, A>,
f: (e: C.Cause<E>) => B,
g: (a: A) => C,
__trace?: string
) {
return fold_(sandbox(self), f, g, __trace)
}
/**
* A more powerful version of `fold` that allows recovering from any kind of failure except interruptions.
*
* @ets_data_first foldCause_
*/
export function foldCause<E, A, B, C>(
f: (e: C.Cause<E>) => B,
g: (a: A) => C,
__trace?: string
) {
return <R>(self: Managed<R, E, A>) => fold_(sandbox(self), f, g, __trace)
}
/**
* Returns a new effect that ignores the success or failure of this effect.
*/
export function ignore<R, E, A>(
self: Managed<R, E, A>,
__trace?: string
): Managed<R, never, void> {
return fold_(self, constVoid, constVoid, __trace)
}
/**
* Returns whether this managed effect is a failure.
*/
export function isFailure<R, E, A>(self: Managed<R, E, A>, __trace?: string) {
return fold_(
self,
() => true,
() => false,
__trace
)
}
/**
* Returns whether this managed effect is a success.
*/
export function isSuccess<R, E, A>(self: Managed<R, E, A>, __trace?: string) {
return fold_(
self,
() => false,
() => true,
__trace
)
}
/**
* Depending on the environment execute this or the other effect
*
* @ets_data_first join_
*/
export function join<R1, E1, A1>(that: Managed<R1, E1, A1>, __trace?: string) {
return <R, E, A>(self: Managed<R, E, A>): Managed<E.Either<R, R1>, E | E1, A | A1> =>
join_(self, that, __trace)
}
/**
* Depending on the environment execute this or the other effect
*/
export function join_<R, E, A, R1, E1, A1>(
self: Managed<R, E, A>,
that: Managed<R1, E1, A1>,
__trace?: string
): Managed<E.Either<R, R1>, E | E1, A | A1> {
return pipe(
environment<E.Either<R, R1>>(),
core.chain(
E.fold(
(r): IO<E | E1, A | A1> => core.provideAll_(self, r),
(r1) => core.provideAll_(that, r1)
),
__trace
)
)
}
/**
* Depending on provided environment returns either this one or the other effect.
*
* @ets_data_first joinEither_
*/
export function joinEither<R2, E2, A2>(that: Managed<R2, E2, A2>, __trace?: string) {
return <R, E, A>(
self: Managed<R, E, A>
): Managed<E.Either<R, R2>, E | E2, E.Either<A, A2>> =>
joinEither_(self, that, __trace)
}
/**
* Depending on provided environment returns either this one or the other effect.
*/
export function joinEither_<R, E, A, R2, E2, A2>(
self: Managed<R, E, A>,
that: Managed<R2, E2, A2>,
__trace?: string
): Managed<E.Either<R, R2>, E | E2, E.Either<A, A2>> {
return pipe(
environment<E.Either<R, R2>>(),
core.chain(
E.fold(
(r0): IO<E | E2, E.Either<A, A2>> =>
core.provideAll_(core.map_(self, E.left), r0),
(r1) => core.provideAll_(core.map_(that, E.right), r1)
),
__trace
)
)
}
/**
* Join self selectively with C
*/
export function identityLeft<C>(__trace?: string) {
return <R, E, A>(
self: Managed<R, E, A>
): Managed<E.Either<R, C>, E, E.Either<A, C>> =>
joinEither_(self, environment<C>(), __trace)
}
/**
* Lifts a synchronous side-effect into a `Managed[R, E, A]`,
* translating any thrown exceptions into typed failed effects using onThrow.
*/
export function tryCatch<E, A>(
f: () => A,
onThrow: (u: unknown) => E,
__trace?: string
): Managed<unknown, E, A> {
return fromEffect(T.tryCatch(f, onThrow), __trace)
}
/**
* Returns an effect whose success is mapped by the specified side effecting
* `f` function, translating any thrown exceptions into typed failed effects.
*
* @ets_data_first mapTryCatch_
*/
export function mapTryCatch<E2, A, B>(
onThrow: (u: unknown) => E2,
f: (a: A) => B,
__trace?: string
) {
return <R, E>(self: Managed<R, E, A>): Managed<R, E | E2, B> =>
mapTryCatch_(self, onThrow, f, __trace)
}
/**
* Returns an effect whose success is mapped by the specified side effecting
* `f` function, translating any thrown exceptions into typed failed effects.
*/
export function mapTryCatch_<R, E, E2, A, B>(
self: Managed<R, E, A>,
onThrow: (u: unknown) => E2,
f: (a: A) => B,
__trace?: string
): Managed<R, E | E2, B> {
return foldM_(
self,
(e) => core.fail(e),
(a) => tryCatch(() => f(a), onThrow),
__trace
)
}
/**
* Returns an effect whose success is mapped by the specified side effecting
* `f` function, translating any thrown exceptions into typed failed effects.
*/
export function mapEffect_<R, E, A, B>(
self: Managed<R, E, A>,
f: (a: A) => B,
__trace?: string
): Managed<R, unknown, B> {
return mapTryCatch_(self, identity, f, __trace)
}
/**
* Returns an effect whose success is mapped by the specified side effecting
* `f` function, translating any thrown exceptions into typed failed effects.
*
* @ets_data_first mapEffect_
*/
export function mapEffect<A, B>(f: (a: A) => B, __trace?: string) {
return <R, E>(self: Managed<R, E, A>): Managed<R, unknown, B> =>
mapEffect_(self, f, __trace)
}
/**
* Preallocates the managed resource, resulting in a Managed that reserves
* and acquires immediately and cannot fail. You should take care that you
* are not interrupted between running preallocate and actually acquiring
* the resource as you might leak otherwise.
*/
export function preallocate<R, E, A>(
self: Managed<R, E, A>,
__trace?: string
): T.Effect<R, E, UIO<A>> {
return T.uninterruptibleMask(({ restore }) =>
pipe(
T.do,
T.bind("releaseMap", () => makeReleaseMap.makeReleaseMap),
T.bind("tp", ({ releaseMap }) =>
T.result(
restore(
T.provideSome_(self.effect, (r: R) => Tp.tuple(r, releaseMap)),
__trace
)
)
),
T.bind("preallocated", ({ releaseMap, tp }) =>
Ex.foldM_(
tp,
(c) =>
pipe(
releaseMap,
releaseAll.releaseAll(Ex.fail(c), T.sequential),
T.zipRight(T.halt(c))
),
({ tuple: [release, a] }) =>
T.succeed(
managedApply(
T.accessM(
({ tuple: [_, releaseMap] }: Tp.Tuple<[unknown, RM.ReleaseMap]>) =>
T.map_(add.add(release)(releaseMap), (_) => Tp.tuple(_, a))
)
)
)
)
),
T.map(({ preallocated }) => preallocated)
)
)
}
/**
* Preallocates the managed resource inside an outer managed, resulting in a
* Managed that reserves and acquires immediately and cannot fail.
*/
export function preallocateManaged<R, E, A>(
self: Managed<R, E, A>,
__trace?: string
): Managed<R, E, UIO<A>> {
return managedApply(
T.map_(
self.effect,
({ tuple: [release, a] }) =>
Tp.tuple(
release,
managedApply(
T.accessM(
({ tuple: [_, releaseMap] }: Tp.Tuple<[unknown, RM.ReleaseMap]>) =>
T.map_(add.add(release)(releaseMap), (_) => Tp.tuple(_, a))
)
)
),
__trace
)
)
}
/**
* Provides a layer to the `Managed`, which translates it to another level.
*
* @ets_data_first provideLayer_
*/
export function provideLayer<R2, E2, R>(layer: L.Layer<R2, E2, R>, __trace?: string) {
return <E, A>(self: Managed<R, E, A>): Managed<R2, E2 | E, A> =>
provideLayer_(self, layer, __trace)
}
/**
* Provides a layer to the `Managed`, which translates it to another level.
*/
export function provideLayer_<R, E, A, R2, E2>(
self: Managed<R, E, A>,
layer: L.Layer<R2, E2, R>,
__trace?: string
): Managed<R2, E | E2, A> {
return core.chain_(L.build(layer), (r) => core.provideAll_(self, r), __trace)
}
/**
* Splits the environment into two parts, providing one part using the
* specified layer and leaving the remainder `R0`.
*/
export function provideSomeLayer<R2, E2, R>(
layer: L.Layer<R2, E2, R>,
__trace?: string
) {
return <R0, E, A>(self: Managed<R & R0, E, A>): Managed<R0 & R2, E | E2, A> =>
provideLayer_(self, layer["+++"](L.identity<R0>()), __trace)
}
/**
* Keeps some of the errors, and terminates the fiber with the rest, using
* the specified function to convert the `E` into a `Throwable`.
*
* @ets_data_first refineOrDieWith_
*/
export function refineOrDieWith<E, E1>(
pf: (e: E) => O.Option<E1>,
f: (e: E) => unknown,
__trace?: string
) {
return <R, A>(self: Managed<R, E, A>) => refineOrDieWith_(self, pf, f)
}
/**
* Keeps some of the errors, and terminates the fiber with the rest, using
* the specified function to convert the `E` into a `Throwable`.
*/
export function refineOrDieWith_<R, A, E, E1>(
self: Managed<R, E, A>,
pf: (e: E) => O.Option<E1>,
f: (e: E) => unknown,
__trace?: string
) {
return catchAll_(self, (e) =>
pipe(
e,
pf,
O.fold(
() => die(f(e), __trace),
(e1) => core.fail(e1, __trace)
)
)
)
}
/**
* Keeps some of the errors, and terminates the fiber with the rest
*
* @ets_data_first refineOrDie_
*/
export function refineOrDie<E, E1>(pf: (e: E) => O.Option<E1>, __trace?: string) {
return <R, A>(self: Managed<R, E, A>) => refineOrDie_(self, pf, __trace)
}
/**
* Keeps some of the errors, and terminates the fiber with the rest
*/
export function refineOrDie_<R, A, E, E1>(
self: Managed<R, E, A>,
pf: (e: E) => O.Option<E1>,
__trace?: string
) {
return refineOrDieWith_(self, pf, identity, __trace)
}
/**
* Returns a managed that dies with the specified `unknown`. This method
* can be used for terminating a fiber because a defect has been
* detected in the code.
*/
export function die(e: unknown, __trace?: string) {
return fromEffect(T.die(e, __trace))
}
/**
* Returns a managed that dies with the specified `unknown`. This method
* can be used for terminating a fiber because a defect has been
* detected in the code.
*/
export function dieWith(e: () => unknown, __trace?: string) {
return fromEffect(T.dieWith(e, __trace))
}
/**
* Returns an effect that dies with a [[java.lang.RuntimeException]] having the
* specified text message. This method can be used for terminating a fiber
* because a defect has been detected in the code.
*/
export function dieMessage(message: string, __trace?: string) {
return die(new RuntimeError(message), __trace)
}
/**
* Continue with the returned computation if the `PartialFunction` matches,
* translating the successful match into a failure, otherwise continue with
* our held value.
*
* @ets_data_first rejectM_
*/
export function rejectM<A, R1, E1>(
pf: (a: A) => O.Option<Managed<R1, E1, E1>>,
__trace?: string
) {
return <R, E>(self: Managed<R, E, A>): Managed<R & R1, E | E1, A> =>
rejectM_(self, pf, __trace)
}
/**
* Continue with the returned computation if the `PartialFunction` matches,
* translating the successful match into a failure, otherwise continue with
* our held value.
*/
export function rejectM_<R, E, A, R1, E1>(
self: Managed<R, E, A>,
pf: (a: A) => O.Option<Managed<R1, E1, E1>>,
__trace?: string
) {
return core.chain_(self, (a) =>
O.fold_(
pf(a),
() => succeed(a, __trace),
(_) => core.chain_(_, (e1) => core.fail(e1), __trace)
)
)
}
/**
* Fail with the returned value if the `PartialFunction` matches, otherwise
* continue with our held value.
*
* @ets_data_first reject_
*/
export function reject<A, E1>(pf: (a: A) => O.Option<E1>, __trace?: string) {
return <R, E>(self: Managed<R, E, A>) => reject_(self, pf, __trace)
}
/**
* Fail with the returned value if the `PartialFunction` matches, otherwise
* continue with our held value.
*/
export function reject_<R, E, A, E1>(
self: Managed<R, E, A>,
pf: (a: A) => O.Option<E1>,
__trace?: string
) {
return rejectM_(self, (x) => pipe(x, pf, O.map(core.fail)), __trace)
}
/**
* Runs all the finalizers associated with this scope. This is useful to
* conceptually "close" a scope when composing multiple managed effects.
* Note that this is only safe if the result of this managed effect is valid
* outside its scope.
*/
export function release<R, E, A>(self: Managed<R, E, A>, __trace?: string) {
return fromEffect(core.useNow(self), __trace)
}
/**
* Returns an effect that retries this effect with the specified schedule when it fails, until
* the schedule is done, then both the value produced by the schedule together with the last
* error are passed to the specified recovery function.
*/
export function retryOrElseEither_<R, E, A, R1, O, R2, E2, A2>(
self: Managed<R, E, A>,
policy: Schedule<R1, E, O>,
orElse: (e: E, o: O) => Managed<R2, E2, A2>,
__trace?: string
): Managed<R & R1 & R2 & HasClock, E2, E.Either<A2, A>> {
return managedApply(
T.map_(
T.accessM(
({
tuple: [env, releaseMap]
}: Tp.Tuple<[R & R1 & R2 & HasClock, RM.ReleaseMap]>) =>
T.provideAll_(
T.retryOrElseEither_(
T.provideAll_(self.effect, Tp.tuple(env, releaseMap)),
policy,
(e, o) => T.provideAll_(orElse(e, o).effect, Tp.tuple(env, releaseMap)),
__trace
),
env
)
),
E.fold(
({ tuple: [f, a] }) => Tp.tuple<[RM.Finalizer, E.Either<A2, A>]>(f, E.left(a)),
({ tuple: [f, a] }) => Tp.tuple<[RM.Finalizer, E.Either<A2, A>]>(f, E.right(a))
)
)
)
}
/**
* Returns an effect that retries this effect with the specified schedule when it fails, until
* the schedule is done, then both the value produced by the schedule together with the last
* error are passed to the specified recovery function.
*
* @ets_data_first retryOrElseEither_
*/
export function retryOrElseEither<E, R1, O, R2, E2, A2>(
policy: Schedule<R1, E, O>,
orElse: (e: E, o: O) => Managed<R2, E2, A2>,
__trace?: string
) {
return <R, A>(self: Managed<R, E, A>) =>
retryOrElseEither_(self, policy, orElse, __trace)
}
/**
* Retries with the specified schedule, until it fails, and then both the
* value produced by the schedule together with the last error are passed to
* the recovery function.
*/
export function retryOrElse_<R, E, A, R1, O, R2, E2, A2>(
self: Managed<R, E, A>,
policy: Schedule<R1, E, O>,
orElse: (e: E, o: O) => Managed<R2, E2, A2>,
__trace?: string
): Managed<R & R1 & R2 & HasClock, E2, A | A2> {
return core.map_(
retryOrElseEither_(self, policy, orElse, __trace),
E.fold(identity, identity)
)
}
/**
* Retries with the specified schedule, until it fails, and then both the
* value produced by the schedule together with the last error are passed to
* the recovery function.
*
* @ets_data_first retryOrElse_
*/
export function retryOrElse<E, R1, O, R2, E2, A2>(
policy: Schedule<R1, E, O>,
orElse: (e: E, o: O) => Managed<R2, E2, A2>,
__trace?: string
) {
return <R, A>(self: Managed<R, E, A>) => retryOrElse_(self, policy, orElse, __trace)
}
/**
* Retries with the specified retry policy.
* Retries are done following the failure of the original `io` (up to a fixed maximum with
* `once` or `recurs` for example), so that that `io.retry(Schedule.once)` means
* "execute `io` and in case of failure, try again once".
*/
export function retry_<R, E, A, R1, O>(
self: Managed<R, E, A>,
policy: Schedule<R1, E, O>,
__trace?: string
): Managed<R & R1 & HasClock, E, A> {
return retryOrElse_(self, policy, (e, _) => core.fail(e), __trace)
}
/**
* Retries with the specified retry policy.
* Retries are done following the failure of the original `io` (up to a fixed maximum with
* `once` or `recurs` for example), so that that `io.retry(Schedule.once)` means
* "execute `io` and in case of failure, try again once".
*
* @ets_data_first retry_
*/
export function retry<R1, E, O>(policy: Schedule<R1, E, O>, __trace?: string) {
return <R, A>(self: Managed<R, E, A>): Managed<R & R1 & HasClock, E, A> =>
retry_(self, policy, __trace)
}
/**
* Returns an effect that semantically runs the effect on a fiber,
* producing an `Exit` for the completion value of the fiber.
*/
export function result<R, E, A>(
self: Managed<R, E, A>,
__trace?: string
): Managed<R, never, Ex.Exit<E, A>> {
return core.foldCauseM_(
self,
(x) => pipe(x, Ex.halt, succeed),
(x) => pipe(x, Ex.succeed, succeed),
__trace
)
}
/**
* Exposes the full cause of failure of this effect.
*/
export function sandbox<R, E, A>(self: Managed<R, E, A>, __trace?: string) {
return managedApply(T.sandbox(self.effect, __trace))
}
/**
* The inverse operation to `sandbox`. Submerges the full cause of failure.
*/
export function unsandbox<R, E, A>(self: Managed<R, C.Cause<E>, A>) {
return mapErrorCause_(self, C.flatten)
}
/**
* Companion helper to `sandbox`. Allows recovery, and partial recovery, from
* errors and defects alike.
*
* @ets_data_first sandboxWith_
*/
export function sandboxWith<R, E, A, R2, E2, B>(
f: (_: Managed<R, C.Cause<E>, A>) => Managed<R2, C.Cause<E2>, B>
) {
return (self: Managed<R, E, A>) => sandboxWith_(self, f)
}
/**
* Companion helper to `sandbox`. Allows recovery, and partial recovery, from
* errors and defects alike.
*/
export function sandboxWith_<R, E, A, R2, E2, B>(
self: Managed<R, E, A>,
f: (_: Managed<R, C.Cause<E>, A>) => Managed<R2, C.Cause<E2>, B>
) {
return unsandbox(f(sandbox(self)))
}
/**
* Zips this effect with its environment
*/
export function second<R, E, A>(self: Managed<R, E, A>) {
return core.zip_(environment<R>(), self)
}
/**
* Converts an option on values into an option on errors.
*/
export function some<R, E, A>(
self: Managed<R, E, O.Option<A>>
): Managed<R, O.Option<E>, A> {
return foldM_(
self,
(x) => pipe(x, O.some, core.fail),
O.fold(() => core.fail(O.none), succeed)
)
}
/**
* Extracts the optional value, or returns the given 'orElse'.
*
* @ets_data_first someOrElse_
*/
export function someOrElse<B>(orElse: () => B) {
return <R, E, A>(self: Managed<R, E, O.Option<A>>): Managed<R, E, A | B> =>
someOrElse_(self, orElse)
}
/**
* Extracts the optional value, or returns the given 'orElse'.
*/
export function someOrElse_<R, E, A, B>(
self: Managed<R, E, O.Option<A>>,
orElse: () => B
) {
return core.map_(self, O.getOrElse(orElse))
}
/**
* Extracts the optional value, or executes the effect 'orElse'.
*
* @ets_data_first someOrElseM_
*/
export function someOrElseM<R1, E1, B>(orElse: Managed<R1, E1, B>) {
return <R, E, A>(self: Managed<R, E, O.Option<A>>) => someOrElseM_(self, orElse)
}
/**
* Extracts the optional value, or executes the effect 'orElse'.
*/
export function someOrElseM_<R, E, A, R1, E1, B>(
self: Managed<R, E, O.Option<A>>,
orElse: Managed<R1, E1, B>
) {
return core.chain_(
self,
O.fold((): Managed<R1, E1, A | B> => orElse, succeed)
)
}
/**
* Extracts the optional value, or fails with the given error 'e'.
*
* @ets_data_first someOrFail_
*/
export function someOrFail<E1>(e: () => E1) {
return <R, E, A>(self: Managed<R, E, O.Option<A>>): Managed<R, E1 | E, A> =>
someOrFail_(self, e)
}
/**
* Extracts the optional value, or fails with the given error 'e'.
*/
export function someOrFail_<R, E, A, E1>(
self: Managed<R, E, O.Option<A>>,
e: () => E1
) {
return core.chain_(
self,
O.fold(() => core.fail(e()), succeed)
)
}
/**
* Extracts the optional value, or fails with a `NoSuchElementException`
*/
export function someOrFailException<R, E, A>(
self: Managed<R, E, O.Option<A>>
): Managed<R, E | NoSuchElementException, A> {
return someOrFail_(self, () => new NoSuchElementException())
}
/**
* Returns an effect that effectfully peeks at the failure or success of the acquired resource.
*/
export function tapBoth_<R, E, A, R1, E1, R2, E2, X, Y>(
self: Managed<R, E, A>,
f: (e: E) => Managed<R1, E1, X>,
g: (a: A) => Managed<R2, E2, Y>
): Managed<R & R1 & R2, E | E1 | E2, A> {
return foldM_(
self,
(e) => core.chain_(f(e), () => core.fail(e)),
(a) => core.map_(g(a), () => a)
)
}
/**
* Returns an effect that effectfully peeks at the failure or success of the acquired resource.
*
* @ets_data_first tapBoth_
*/
export function tapBoth<E, A, R1, E1, R2, E2, X, Y>(
f: (e: E) => Managed<R1, E1, X>,
g: (a: A) => Managed<R2, E2, Y>
) {
return <R>(self: Managed<R, E, A>) => tapBoth_(self, f, g)
}
/**
* Returns an effect that effectually peeks at the cause of the failure of
* the acquired resource.
*/
export function tapCause_<R, E, A, R1, E1, X>(
self: Managed<R, E, A>,
f: (c: Cause<E>) => Managed<R1, E1, X>
): Managed<R & R1, E | E1, A> {
return catchAllCause_(self, (c) => core.chain_(f(c), () => halt(c)))
}
/**
* Returns an effect that effectually peeks at the cause of the failure of
* the acquired resource.
*
* @ets_data_first tapCause_
*/
export function tapCause<E, R1, E1, X>(f: (c: Cause<E>) => Managed<R1, E1, X>) {
return <R, A>(self: Managed<R, E, A>): Managed<R & R1, E | E1, A> =>
tapCause_(self, f)
}
/**
* Returns an effect that effectfully peeks at the failure of the acquired resource.
*/
export function tapError_<R, E, A, R1, E1, X>(
self: Managed<R, E, A>,
f: (e: E) => Managed<R1, E1, X>
): Managed<R & R1, E | E1, A> {
return tapBoth_(self, f, succeed)
}
/**
* Returns an effect that effectfully peeks at the failure of the acquired resource.
*
* @ets_data_first tapError_
*/
export function tapError<E, R1, E1, X>(f: (e: E) => Managed<R1, E1, X>) {
return <R, A>(self: Managed<R, E, A>) => tapError_(self, f)
}
/**
* Like `tap`, but uses a function that returns a Effect value rather than a
* Managed value.
*
* @ets_data_first tapM_
*/
export function tapM<A, R1, E1, X>(f: (a: A) => Effect<R1, E1, X>) {
return <R, E>(self: Managed<R, E, A>): Managed<R & R1, E | E1, A> => tapM_(self, f)
}
/**
* Like `tap`, but uses a function that returns a Effect value rather than a
* Managed value.
*/
export function tapM_<R, E, A, R1, E1, X>(
self: Managed<R, E, A>,
f: (a: A) => Effect<R1, E1, X>
) {
return core.mapM_(self, (a) => T.as_(f(a), a))
}
/**
* Returns a new effect that executes this one and times the acquisition of the resource.
*/
export function timed<R, E, A>(
self: Managed<R, E, A>
): Managed<R & HasClock, E, Tp.Tuple<[number, A]>> {
return managedApply(
T.chain_(
T.environment<Tp.Tuple<[R, RM.ReleaseMap]>>(),
({ tuple: [r, releaseMap] }) =>
T.provideSome_(
T.map_(
T.timed(T.provideAll_(self.effect, Tp.tuple(r, releaseMap))),
({
tuple: [
duration,
{
tuple: [fin, a]
}
]
}) => Tp.tuple(fin, Tp.tuple(duration, a))
),
(r: Tp.Tuple<[R & HasClock, RM.ReleaseMap]>) => r.get(0)
)
)
)
}
/**
* Returns an effect that will timeout this resource, returning `None` if the
* timeout elapses before the resource was reserved and acquired.
* If the reservation completes successfully (even after the timeout) the release action will be run on a new fiber.
* `Some` will be returned if acquisition and reservation complete in time
*/
export function timeout_<R, E, A>(self: Managed<R, E, A>, d: number) {
return managedApply(
T.uninterruptibleMask(({ restore }) =>
T.gen(function* (_) {
const env = yield* _(T.environment<Tp.Tuple<[R & HasClock, RM.ReleaseMap]>>())
const {
tuple: [r, outerReleaseMap]
} = env
const innerReleaseMap = yield* _(makeReleaseMap.makeReleaseMap)
const earlyRelease = yield* _(
add.add((exit) => releaseAll.releaseAll(exit, T.sequential)(innerReleaseMap))(
outerReleaseMap
)
)
const raceResult: E.Either<
F.Fiber<E, Tp.Tuple<[RM.Finalizer, A]>>,
A
> = yield* _(
restore(
T.provideAll_(
T.raceWith_(
T.provideAll_(self.effect, Tp.tuple(r, innerReleaseMap)),
T.as_(T.sleep(d), O.none),
(result, sleeper) =>
T.zipRight_(
F.interrupt(sleeper),
T.done(Ex.map_(result, (tp) => E.right(tp.get(1))))
),
(_, resultFiber) => T.succeed(E.left(resultFiber))
),
r
)
)
)
const a = yield* _(
E.fold_(
raceResult,
(f) =>
T.as_(
T.chain_(T.fiberId, (id) =>
T.forkDaemon(
T.ensuring_(
F.interrupt(f),
releaseAll.releaseAll(
Ex.interrupt(id),
T.sequential
)(innerReleaseMap)
)
)
),
O.none
),
(v) => T.succeed(O.some(v))
)
)
return Tp.tuple(earlyRelease, a)
})
)
)
}
/**
* Returns an effect that will timeout this resource, returning `None` if the
* timeout elapses before the resource was reserved and acquired.
* If the reservation completes successfully (even after the timeout) the release action will be run on a new fiber.
* `Some` will be returned if acquisition and reservation complete in time
*
* @ets_data_first timeout_
*/
export function timeout(d: number) {
return <R, E, A>(self: Managed<R, E, A>): Managed<R & HasClock, E, O.Option<A>> =>
timeout_(self, d)
}
/**
* Constructs a layer from this managed resource.
*
* @ets_data_first toLayer_
*/
export function toLayer<A>(
tag: Tag<A>
): <R, E>(self: Managed<R, E, A>) => L.Layer<R, E, Has<A>> {
return L.fromManaged(tag)
}
/**
* Constructs a layer from this managed resource.
*/
export function toLayer_<R, E, A>(
self: Managed<R, E, A>,
tag: Tag<A>
): L.Layer<R, E, Has<A>> {
return toLayer(tag)(self)
}
/**
* Constructs a layer from this managed resource, which must return one or
* more services.
*/
export function toLayerMany<Tags extends Tag<any>[]>(...tags: Tags) {
return <R, E>(
self: Managed<
R,
E,
UnionToIntersection<
{
[k in keyof Tags & number]: [Tags[k]] extends [Tag<infer A>] ? Has<A> : never
}[number]
>
>
) =>
L.fromRawManaged(
core.map_(
self,
(
r
): UnionToIntersection<
{
[k in keyof Tags & number]: [Tags[k]] extends [Tag<infer A>]
? Has<A>
: never
}[number]
> => {
const env: any = {}
for (const tag of tags) {
env[tag.key] = tag.read(r as any)
}
return env
}
)
)
}
/**
* Return unit while running the effect
*/
export function asUnit<R, E, A>(self: Managed<R, E, A>): Managed<R, E, void> {
return as_(self, undefined)
}
/**
* The moral equivalent of `if (!p) exp` when `p` has side-effects
*
* @ets_data_first unlessM_
*/
export function unlessM<R1, E1>(b: Managed<R1, E1, boolean>) {
return <R, E, A>(self: Managed<R, E, A>): Managed<R1 & R, E1 | E, void> =>
unlessM_(self, b)
}
/**
* The moral equivalent of `if (!p) exp` when `p` has side-effects
*/
export function unlessM_<R, E, A, R1, E1>(
self: Managed<R, E, A>,
b: Managed<R1, E1, boolean>
): Managed<R1 & R, E1 | E, void> {
return core.chain_(b, (b) => (b ? unit : asUnit(self)))
}
/**
* The moral equivalent of `if (!p) exp`
*
* @ets_data_first unless_
*/
export function unless(b: () => boolean) {
return unlessM(core.succeedWith(b))
}
/**
* The moral equivalent of `if (!p) exp`
*/
export function unless_<R, E, A>(self: Managed<R, E, A>, b: () => boolean) {
return unless(b)(self)
}
/**
* Maps this effect to the specified constant while preserving the
* effects of this effect.
*/
export function as_<R, E, A, B>(self: Managed<R, E, A>, b: B) {
return core.map_(self, () => b)
}
/**
* Maps this effect to the specified constant while preserving the
* effects of this effect.
*
* @ets_data_first as_
*/
export function as<B>(b: B) {
return <R, E, A>(self: Managed<R, E, A>) => as_(self, b)
}
/**
* Maps the success value of this effect to an optional value.
*/
export function asSome<R, E, A>(self: Managed<R, E, A>) {
return core.map_(self, O.some)
}
/**
* Maps the error value of this effect to an optional value.
*/
export function asSomeError<R, E, A>(self: Managed<R, E, A>) {
return mapError_(self, O.some)
}
/**
* Maps the success value of this effect to a service.
*
* @ets_data_first asService_
*/
export function asService<A>(tag: Tag<A>) {
return <R, E>(self: Managed<R, E, A>) => asService_(self, tag)
}
/**
* Maps the success value of this effect to a service.
*/
export function asService_<R, E, A>(self: Managed<R, E, A>, tag: Tag<A>) {
return core.map_(self, tag.has)
}
/**
* Executes the this effect and then provides its output as an environment to the second effect
*/
export function andThen_<R, E, A, E1, B>(
self: Managed<R, E, A>,
that: Managed<A, E1, B>
) {
return core.chain_(self, (a) => core.provideAll_(that, a))
}
/**
* Executes the this effect and then provides its output as an environment to the second effect
*
* @ets_data_first andThen_
*/
export function andThen<A, E1, B>(that: Managed<A, E1, B>) {
return <R, E>(self: Managed<R, E, A>) => andThen_(self, that)
}
/**
* Returns an effect whose failure and success channels have been mapped by
* the specified pair of functions, `f` and `g`.
*
* @ets_data_first bimap_
*/
export function bimap<E, A, E1, A1>(f: (e: E) => E1, g: (a: A) => A1) {
return <R>(self: Managed<R, E, A>) => bimap_(self, f, g)
}
/**
* Returns an effect whose failure and success channels have been mapped by
* the specified pair of functions, `f` and `g`.
*/
export function bimap_<R, E, A, E1, A1>(
self: Managed<R, E, A>,
f: (e: E) => E1,
g: (a: A) => A1
) {
return core.map_(mapError_(self, f), g)
}
/**
* Joins with environment passing self selectively on the right side
*/
export function right<C>() {
return <R, E, A>(self: Managed<R, E, A>) => joinEither_(environment<C>(), self)
}
/**
* Joins with environment passing self selectively on the left side
*/
export function left<C>() {
return <R, E, A>(self: Managed<R, E, A>) => joinEither_(self, environ