Skip to content

Commit

Permalink
feat(Cause): add Cause#squashWith
Browse files Browse the repository at this point in the history
  • Loading branch information
0x706b committed Jun 16, 2022
1 parent a2dde85 commit eecc62c
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 59 deletions.
6 changes: 6 additions & 0 deletions .changeset/clever-impalas-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@fncts/base": patch
"@fncts/io": patch
---

feat(Cause): add Cause#squashWith
86 changes: 38 additions & 48 deletions packages/base/src/data/Cause/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,15 @@ export function isInterrupt<E>(self: Cause<E>): self is Interrupt {
return self._tag === CauseTag.Interrupt;
}

/**
* Determines if the `Cause` contains an interruption.
*
* @tsplus getter fncts.Cause isInterrupted
*/
export function isInterrupted<E>(self: Cause<E>): boolean {
return self.find((cause) => (cause.isInterrupt() ? Just(cause) : Nothing())).isJust();
}

/**
* A type-guard matching `Traced`
*
Expand Down Expand Up @@ -689,8 +698,10 @@ export function interruptOption<E>(self: Cause<E>): Maybe<FiberId> {
*
* @tsplus getter fncts.Cause interruptors
*/
export function interruptors<E>(self: Cause<E>): ReadonlySet<FiberId> {
return self.foldLeft(new Set(), (s, c) => (c._tag === CauseTag.Interrupt ? Just(s.add(c.id)) : Nothing()));
export function interruptors<E>(self: Cause<E>): HashSet<FiberId> {
return self.foldLeft(HashSet.makeDefault(), (s, c) =>
c._tag === CauseTag.Interrupt ? Just(s.add(c.id)) : Nothing(),
);
}

/**
Expand Down Expand Up @@ -915,52 +926,31 @@ export function sequenceCauseMaybe<E>(self: Cause<Maybe<E>>): Maybe<Cause<E>> {
return Eval.run(sequenceCauseMaybeEval(self));
}

// /**
// * Squashes a `Cause` down to a single `Error`, chosen to be the
// * "most important" `Error`.
// */
// export function squash_<Id>(
// S: P.Show<Id>
// ): <E>(cause: Cause<E>, f: (e: E) => unknown) => unknown {
// return (cause, f) =>
// cause.failureOption
// .map(f)
// .orElse(
// interrupted(cause)
// ? Maybe.just<unknown>(
// new InterruptedException(
// "Interrupted by fibers: " +
// Array.from(interruptors(cause))
// .map((id) => S.show(id))
// .join(", ")
// )
// )
// : Maybe.nothing()
// )
// .orElse(defects(cause).head)
// .getOrElse(new InterruptedException("Interrupted"));
// }

// /**
// * @tsplus getter PCause squash
// */
// export function squash0<Id, E>(self: Cause<E>) {
// return (S: P.Show<Id>) =>
// (f: (e: E) => unknown): unknown =>
// squash_(S)(self, f);
// }

// /**
// * Squashes a `Cause` down to a single `Error`, chosen to be the
// * "most important" `Error`.
// *
// * @dataFirst squash_
// */
// export function squash<Id>(
// S: P.Show<Id>
// ): <E>(f: (e: E) => unknown) => (cause: Cause<E>) => unknown {
// return (f) => (cause) => squash_(S)(cause, f);
// }
/**
* Squashes a `Cause` down to a single `Error`, chosen to be the
* "most important" `Error`.
*
* @tsplus fluent fncts.Cause squashWith
*/
export function squashWith_<E>(self: Cause<E>, f: (e: E) => unknown): unknown {
return self.failureMaybe
.map(f)
.orElse(
self.isInterrupted
? Just(
new InterruptedException(
"Interrupted by fibers: " +
self.interruptors
.flatMap((id) => id.ids)
.map((id) => `#${id}`)
.join(", "),
),
)
: Nothing(),
)
.orElse(self.defects.head)
.getOrElse(new InterruptedException());
}

/**
* Constructs a `Cause` from two `Cause`s, representing sequential failures.
Expand Down
2 changes: 1 addition & 1 deletion packages/base/src/data/exceptions/InterruptedException.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type InterruptedExceptionTypeId = typeof InterruptedExceptionTypeId;

export class InterruptedException {
readonly _typeId: InterruptedExceptionTypeId = InterruptedExceptionTypeId;
constructor(readonly message: string) {}
constructor(readonly message?: string) {}
}

export function isInterruptedException(u: unknown): u is InterruptedException {
Expand Down
18 changes: 9 additions & 9 deletions packages/io/src/IO/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ export function asyncInterrupt<R, E, A>(
return new Async(register, blockingOn, __tsplusTrace);
}

// /**
// * Attempts to convert defects into a failure, throwing away all information
// * about the cause of the failure.
// *
// * @tsplus fluent fncts.io.IO absorbWith
// */
// export function absorbWith_<R, E, A>(ma: IO<R, E, A>, f: (e: E) => unknown, __tsplusTrace?: string) {
// return ma.sandbox.matchIO((cause) => IO.failNow(cause.squash(f)), IO.succeedNow)
// }
/**
* Attempts to convert defects into a failure, throwing away all information
* about the cause of the failure.
*
* @tsplus fluent fncts.io.IO absorbWith
*/
export function absorbWith_<R, E, A>(ma: IO<R, E, A>, f: (e: E) => unknown, __tsplusTrace?: string) {
return ma.sandbox.matchIO((cause) => IO.failNow(cause.squashWith(f)), IO.succeedNow)
}

/**
* @tsplus fluent fncts.io.IO apFirst
Expand Down
2 changes: 1 addition & 1 deletion packages/io/src/IO/api/interrupt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export function interruptibleMask<R, E, A>(k: (restore: InterruptStatusRestore)
*/
export function onInterrupt_<R, E, A, R1>(
ma: IO<R, E, A>,
cleanup: (interruptors: ReadonlySet<FiberId>) => IO<R1, never, any>,
cleanup: (interruptors: HashSet<FiberId>) => IO<R1, never, any>,
): IO<R & R1, E, A> {
return uninterruptibleMask(({ restore }) =>
restore(ma).matchCauseIO(
Expand Down

0 comments on commit eecc62c

Please sign in to comment.