Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

orDie combinator #902

Merged
merged 15 commits into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merged updates in main; refined names; added scaladoc to ForAbortOps
  • Loading branch information
johnhungerford committed Dec 5, 2024
commit d4329c0628783fb10024a2ce82cefd0551b40da1
36 changes: 33 additions & 3 deletions kyo-combinators/shared/src/main/scala/kyo/Combinators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ extension [A, S, E](effect: A < (Abort[E] & S))
): Result[E, A] < S =
Abort.run[E](effect)

def forAbort[E1 <: E]: SomeAbortOps[A, S, E, E1] = SomeAbortOps(effect)
def forAbort[E1 <: E]: ForAbortOps[A, S, E, E1] = ForAbortOps(effect)

/** Translates the Abort effect to a Choice effect.
*
Expand Down Expand Up @@ -435,7 +435,12 @@ extension [A, S, E](effect: A < (Abort[Absent] & S))
case res: Result.Panic => Abort.get(res)
end extension

class SomeAbortOps[A, S, E, E1 <: E](effect: A < (Abort[E] & S)) extends AnyVal:
class ForAbortOps[A, S, E, E1 <: E](effect: A < (Abort[E] & S)) extends AnyVal:
/** Handles the partial Abort[E1] effect and returns its result as a `Result[E1, A]`.
*
* @return
* A computation that produces the result of this computation with the Abort[E1] effect handled
*/
def result[ER](
using
ev: E => E1 | ER,
Expand All @@ -446,6 +451,11 @@ class SomeAbortOps[A, S, E, E1 <: E](effect: A < (Abort[E] & S)) extends AnyVal:
): Result[E1, A] < (S & reduce.SReduced) =
Abort.run[E1](effect.asInstanceOf[A < (Abort[E1 | ER] & S)])

/** Handles the partial Abort[E1] effect and applies a recovery function to the error.
*
* @return
* A computation that produces the result of this computation with the Abort[E1] effect handled
*/
def catching[ER](
using
ev: E => E1 | ER,
Expand All @@ -462,6 +472,11 @@ class SomeAbortOps[A, S, E, E1 <: E](effect: A < (Abort[E] & S)) extends AnyVal:
case ab @ Result.Panic(_) => Abort.get(ab.asInstanceOf[Result[Nothing, Nothing]])
})

/** Handles the partial Abort[E1] effect and applies a partial recovery function to the error.
*
* @return
* A computation that produces the result of this computation with Abort[E1] effect
*/
def catchingSome[ER](
using
ev: E => E1 | ER,
Expand All @@ -477,6 +492,11 @@ class SomeAbortOps[A, S, E, E1 <: E](effect: A < (Abort[E] & S)) extends AnyVal:
case Result.Success(a) => a
}

/** Translates the partial Abort[E1] effect to a Choice effect.
*
* @return
* A computation that produces the result of this computation with the Abort[E1] effect translated to Choice
*/
def toChoice[ER](
using
ev: E => E1 | ER,
Expand All @@ -487,6 +507,11 @@ class SomeAbortOps[A, S, E, E1 <: E](effect: A < (Abort[E] & S)) extends AnyVal:
): A < (S & reduce.SReduced & Choice) =
Abort.run[E1](effect.asInstanceOf[A < (Abort[E1 | ER] & S)]).map(e => Choice.get(e.fold(_ => Nil)(List(_))))
johnhungerford marked this conversation as resolved.
Show resolved Hide resolved

/** Translates the partial Abort[E1] effect to an Abort[Absent] effect in case of failure.
*
* @return
* A computation that produces the result of this computation with the Abort[E1] effect translated to Abort[Absent]
*/
def toEmpty[ER](
using
ev: E => E1 | ER,
Expand All @@ -501,6 +526,11 @@ class SomeAbortOps[A, S, E, E1 <: E](effect: A < (Abort[E] & S)) extends AnyVal:
case s @ Result.Success(_) => Abort.get(s.asInstanceOf[Result[Nothing, A]])
}

/** Translates the partial Abort[E1] effect by swapping the error and success types.
*
* @return
* A computation that produces the failure E1 as result of this computation and the success A as Abort[A] effect
*/
def swap[ER](
using
ev: E => E1 | ER,
Expand All @@ -512,7 +542,7 @@ class SomeAbortOps[A, S, E, E1 <: E](effect: A < (Abort[E] & S)) extends AnyVal:
val handled = Abort.run[E1](effect.asInstanceOf[A < (Abort[E1 | ER] & S)])
handled.map((v: Result[E1, A]) => Abort.get(v.swap))
end swap
end SomeAbortOps
end ForAbortOps

extension [A, S, E](effect: A < (S & Env[E]))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ class AbortCombinatorTest extends Test:
for
nameService <- Kyo.service[HelloService] // Adds Env[NameService] effect
_ <- keepTicking.forkScoped // Adds Async, Abort[IOException], and Resource effects
saluee <- Console.readln
saluee <- Console.readLine
_ <- Kyo.sleep(2.seconds) // Uses Async (semantic blocking)
_ <- nameService.sayHelloTo(saluee) // Lifts Abort[IOException] to Abort[Throwable]
yield ()
Expand Down
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.