Skip to content

Commit

Permalink
data: export Maybe.Empty and Maybe.Defined to the kyo package
Browse files Browse the repository at this point in the history
  • Loading branch information
fwbrasil committed Oct 11, 2024
1 parent e80045f commit ddc9ebc
Show file tree
Hide file tree
Showing 22 changed files with 121 additions and 119 deletions.
53 changes: 26 additions & 27 deletions kyo-combinators/shared/src/main/scala/kyo/Combinators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -226,11 +226,10 @@ extension [A, S](effect: A < S)
* @param condition
* The condition to check
* @return
* A computation that produces the result of this computation wrapped in Maybe.Defined if the condition is satisfied, or Maybe.Empty
* if not
* A computation that produces the result of this computation wrapped in Defined if the condition is satisfied, or Empty if not
*/
def when[S1](condition: => Boolean < S1)(using Frame): Maybe[A] < (S & S1) =
condition.map(c => if c then effect.map(Maybe.Defined.apply) else Maybe.Empty)
condition.map(c => if c then effect.map(Defined.apply) else Empty)

/** Performs this computation catching any Throwable in an Abort[Throwable] effect.
*
Expand All @@ -248,15 +247,15 @@ extension [A, S](effect: A < S)
def tap[S1](f: A => Any < S1)(using Frame): A < (S & S1) =
effect.map(a => f(a).as(a))

/** Performs this computation unless the given condition holds, in which case it returns an Abort[Maybe.Empty] effect.
/** Performs this computation unless the given condition holds, in which case it returns an Abort[Empty] effect.
*
* @param condition
* The condition to check
* @return
* A computation that produces the result of this computation with Abort[Maybe.Empty] effect
* A computation that produces the result of this computation with Abort[Empty] effect
*/
def unless[S1](condition: Boolean < S1)(using Frame): A < (S & S1 & Abort[Maybe.Empty]) =
condition.map(c => if c then Abort.fail(Maybe.Empty) else effect)
def unless[S1](condition: Boolean < S1)(using Frame): A < (S & S1 & Abort[Empty]) =
condition.map(c => if c then Abort.fail(Empty) else effect)

/** Ensures that the specified finalizer is executed after this effect, whether it succeeds or fails. The finalizer will execute when
* the Resource effect is handled.
Expand Down Expand Up @@ -303,19 +302,19 @@ extension [A, S, E](effect: A < (Abort[E] & S))

def someAbortToChoice[E1 <: E](using Frame): SomeAbortToChoiceOps[A, S, E, E1] = SomeAbortToChoiceOps(effect)

/** Translates the Abort[E] effect to an Abort[Maybe.Empty] effect in case of failure.
/** Translates the Abort[E] effect to an Abort[Empty] effect in case of failure.
*
* @return
* A computation that produces the result of this computation with the Abort[E] effect translated to Abort[Maybe.Empty]
* A computation that produces the result of this computation with the Abort[E] effect translated to Abort[Empty]
*/
def abortToEmpty(
using
ct: SafeClassTag[E],
tag: Tag[E],
flat: Flat[A]
)(using Frame): A < (S & Abort[Maybe.Empty]) =
)(using Frame): A < (S & Abort[Empty]) =
effect.handleAbort.map {
case Result.Fail(_) => Abort.fail(Maybe.Empty)
case Result.Fail(_) => Abort.fail(Empty)
case Result.Panic(e) => throw e
case Result.Success(a) => a
}
Expand Down Expand Up @@ -398,36 +397,36 @@ extension [A, S, E](effect: A < (Abort[E] & S))
.map(_.fold(e => throw e.getFailure)(identity))
end extension

extension [A, S, E](effect: A < (Abort[Maybe.Empty] & S))
extension [A, S, E](effect: A < (Abort[Empty] & S))

/** Handles the Abort[Maybe.Empty] effect and returns its result as a `Maybe[A]`.
/** Handles the Abort[Empty] effect and returns its result as a `Maybe[A]`.
*
* @return
* A computation that produces the result of this computation with the Abort[Maybe.Empty] effect handled
* A computation that produces the result of this computation with the Abort[Empty] effect handled
*/
def handleEmptyAbort(using Flat[A], Frame): Maybe[A] < S =
Abort.run[Maybe.Empty](effect).map {
case Result.Fail(_) => Maybe.Empty
Abort.run[Empty](effect).map {
case Result.Fail(_) => Empty
case Result.Panic(e) => throw e
case Result.Success(a) => Maybe.Defined(a)
case Result.Success(a) => Defined(a)
}

/** Translates the Abort[Maybe.Empty] effect to a Choice effect.
/** Translates the Abort[Empty] effect to a Choice effect.
*
* @return
* A computation that produces the result of this computation with the Abort[Maybe.Empty] effect translated to Choice
* A computation that produces the result of this computation with the Abort[Empty] effect translated to Choice
*/
def emptyAbortToChoice(using Flat[A], Frame): A < (S & Choice) =
effect.someAbortToChoice[Maybe.Empty]()
effect.someAbortToChoice[Empty]()

/** Handles the Abort[Maybe.Empty] effect translating it to an Abort[E] effect.
/** Handles the Abort[Empty] effect translating it to an Abort[E] effect.
*
* @return
* A computation that produces the result of this computation with the Abort[Maybe.Empty] effect translated to Abort[E]
* A computation that produces the result of this computation with the Abort[Empty] effect translated to Abort[E]
*/
def emptyAbortToFailure(failure: => E)(using Flat[A], Frame): A < (S & Abort[E]) =
for
res <- effect.handleSomeAbort[Maybe.Empty]()
res <- effect.handleSomeAbort[Empty]()
yield res match
case Result.Fail(_) => Abort.get(Result.Fail(failure))
case Result.Success(a) => Abort.get(Result.success(a))
Expand Down Expand Up @@ -456,10 +455,10 @@ end SomeAbortToChoiceOps

class SomeAbortToEmptyOps[A, S, E, E1 <: E](effect: A < (Abort[E] & S)) extends AnyVal:

/** Handles the Abort[E] effect translating it to an Abort[Maybe.Empty] effect.
/** Handles the Abort[E] effect translating it to an Abort[Empty] effect.
*
* @return
* A computation that produces the result of this computation with Abort[Maybe.Empty] effect
* A computation that produces the result of this computation with Abort[Empty] effect
*/
def apply[ER]()(
using
Expand All @@ -469,9 +468,9 @@ class SomeAbortToEmptyOps[A, S, E, E1 <: E](effect: A < (Abort[E] & S)) extends
reduce: Reducible[Abort[ER]],
flat: Flat[A],
frame: Frame
): A < (S & reduce.SReduced & Abort[Maybe.Empty]) =
): A < (S & reduce.SReduced & Abort[Empty]) =
Abort.run[E1](effect.asInstanceOf[A < (Abort[E1 | ER] & S)]).map {
case Result.Fail(_) => Abort.get(Result.Fail(Maybe.Empty))
case Result.Fail(_) => Abort.get(Result.Fail(Empty))
case p @ Result.Panic(e) => Abort.get(p.asInstanceOf[Result[Nothing, Nothing]])
case s @ Result.Success(a) => Abort.get(s.asInstanceOf[Result[Nothing, A]])
}
Expand Down
12 changes: 6 additions & 6 deletions kyo-combinators/shared/src/main/scala/kyo/Constructors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -156,24 +156,24 @@ extension (kyoObject: Kyo.type)
def fromEither[E, A](either: Either[E, A])(using Frame): A < Abort[E] =
Abort.get(either)

/** Creates an effect from an Option[A] and handles None to Abort[Maybe.Empty].
/** Creates an effect from an Option[A] and handles None to Abort[Empty].
*
* @param option
* The Option[A] to create an effect from
* @return
* An effect that attempts to run the given effect and handles None to Abort[Maybe.Empty].
* An effect that attempts to run the given effect and handles None to Abort[Empty].
*/
def fromOption[A](option: Option[A])(using Frame): A < Abort[Maybe.Empty] =
def fromOption[A](option: Option[A])(using Frame): A < Abort[Empty] =
Abort.get(option)

/** Creates an effect from a Maybe[A] and handles Maybe.Empty to Abort[Maybe.Empty].
/** Creates an effect from a Maybe[A] and handles Empty to Abort[Empty].
*
* @param maybe
* The Maybe[A] to create an effect from
* @return
* An effect that attempts to run the given effect and handles Maybe.Empty to Abort[Maybe.Empty].
* An effect that attempts to run the given effect and handles Empty to Abort[Empty].
*/
def fromMaybe[A](maybe: Maybe[A])(using Frame): A < Abort[Maybe.Empty] =
def fromMaybe[A](maybe: Maybe[A])(using Frame): A < Abort[Empty] =
Abort.get(maybe)

/** Creates an effect from a Result[E, A] and handles Result.Failure[E] to Abort[E].
Expand Down
32 changes: 16 additions & 16 deletions kyo-combinators/shared/src/test/scala/kyo/AbortCombinatorTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ class AbortCombinatorTest extends Test:

"should construct from option" in {
val effect = Kyo.fromOption(None)
assert(Abort.run[Maybe.Empty](effect).eval.failure.get == Maybe.Empty)
assert(Abort.run[Empty](effect).eval.failure.get == Empty)
val effect1 = Kyo.fromOption(Some(1))
assert(Abort.run[Maybe.Empty](effect1).eval.getOrElse(-1) == 1)
assert(Abort.run[Empty](effect1).eval.getOrElse(-1) == 1)
}

"should construct from maybe" in {
val effect = Kyo.fromMaybe(Maybe.Empty)
assert(Abort.run[Maybe.Empty](effect).eval.failure.get == Maybe.Empty)
val effect1 = Kyo.fromMaybe(Maybe.Defined(1))
assert(Abort.run[Maybe.Empty](effect1).eval.getOrElse(-1) == 1)
val effect = Kyo.fromMaybe(Empty)
assert(Abort.run[Empty](effect).eval.failure.get == Empty)
val effect1 = Kyo.fromMaybe(Defined(1))
assert(Abort.run[Empty](effect1).eval.getOrElse(-1) == 1)
}

"should construct from a throwing block" in {
Expand Down Expand Up @@ -97,25 +97,25 @@ class AbortCombinatorTest extends Test:
"should convert all abort to empty" in {
val failure: Int < Abort[String] =
Abort.fail("failure")
val failureEmpty: Int < Abort[Maybe.Empty] = failure.abortToEmpty
val handledFailureEmpty = Abort.run[Maybe.Empty](failureEmpty)
assert(handledFailureEmpty.eval == Result.Fail(Maybe.Empty))
val success: Int < Abort[String] = 23
val successEmpty: Int < Abort[Maybe.Empty] = success.abortToEmpty
val handledSuccessEmpty = Abort.run[Any](successEmpty)
val failureEmpty: Int < Abort[Empty] = failure.abortToEmpty
val handledFailureEmpty = Abort.run[Empty](failureEmpty)
assert(handledFailureEmpty.eval == Result.Fail(Empty))
val success: Int < Abort[String] = 23
val successEmpty: Int < Abort[Empty] = success.abortToEmpty
val handledSuccessEmpty = Abort.run[Any](successEmpty)
assert(handledSuccessEmpty.eval == Result.Success(23))
}

"should convert some abort to empty" in {
val failure: Int < Abort[String | Boolean | Double | Int] =
Abort.fail("failure")
val failureEmpty: Int < Abort[Maybe.Empty | Boolean | Double | Int] =
val failureEmpty: Int < Abort[Empty | Boolean | Double | Int] =
failure.someAbortToEmpty[String]()
val handledFailureEmpty = Choice.run(failureEmpty)
val handledFailureAbort = Abort.run[Any](handledFailureEmpty)
assert(handledFailureAbort.eval == Result.fail(Maybe.Empty))
assert(handledFailureAbort.eval == Result.fail(Empty))
val success: Int < Abort[String | Boolean | Double | Int] = 23
val successEmpty: Int < (Abort[Maybe.Empty | Boolean | Double | Int]) =
val successEmpty: Int < (Abort[Empty | Boolean | Double | Int]) =
success.someAbortToEmpty[String]()
val handledSuccessEmpty = Abort.run[Any](successEmpty)
assert(handledSuccessEmpty.eval == Result.success(23))
Expand Down Expand Up @@ -282,7 +282,7 @@ class AbortCombinatorTest extends Test:
"should convert some abort to empty" in {
val effect: Int < Abort[String | Boolean] = Abort.fail("error")
val emptyEffect = effect.someAbortToEmpty[String]()
assert(Abort.run[Any](emptyEffect).eval == Result.fail(Maybe.Empty))
assert(Abort.run[Any](emptyEffect).eval == Result.fail(Empty))

val effect2: Int < Abort[String | Boolean] = 42
val emptyEffect2 = effect2.someAbortToEmpty[String]()
Expand Down
16 changes: 8 additions & 8 deletions kyo-combinators/shared/src/test/scala/kyo/ConstructorsTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,24 @@ class ConstructorsTest extends Test:
val someEffect = Kyo.fromOption(Some(42))
val noneEffect = Kyo.fromOption(None)

val someResult = Abort.run[Maybe.Empty](someEffect).eval
val noneResult = Abort.run[Maybe.Empty](noneEffect).eval
val someResult = Abort.run[Empty](someEffect).eval
val noneResult = Abort.run[Empty](noneEffect).eval

assert(someResult == Result.success(42))
assert(noneResult == Result.fail(Maybe.Empty))
assert(noneResult == Result.fail(Empty))
}
}

"fromMaybe" - {
"should create an effect from Maybe[A]" in {
val definedEffect = Kyo.fromMaybe(Maybe.Defined(42))
val emptyEffect = Kyo.fromMaybe(Maybe.Empty)
val definedEffect = Kyo.fromMaybe(Defined(42))
val emptyEffect = Kyo.fromMaybe(Empty)

val definedResult = Abort.run[Maybe.Empty](definedEffect).eval
val emptyResult = Abort.run[Maybe.Empty](emptyEffect).eval
val definedResult = Abort.run[Empty](definedEffect).eval
val emptyResult = Abort.run[Empty](emptyEffect).eval

assert(definedResult == Result.success(42))
assert(emptyResult == Result.fail(Maybe.Empty))
assert(emptyResult == Result.fail(Empty))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class EffectCombinatorTest extends Test:
val getState = IO(state)
val effectWhen = (toggleState *> getState).when(getState)
effectWhen.map { handledEffectWhen =>
assert(handledEffectWhen == Maybe.Empty)
assert(handledEffectWhen == Empty)
}
}
"condition is true" in run {
Expand All @@ -128,7 +128,7 @@ class EffectCombinatorTest extends Test:
val getState = IO(state)
val effectWhen = (toggleState *> getState).when(getState)
effectWhen.map { handledEffectWhen =>
assert(handledEffectWhen == Maybe.Defined(false))
assert(handledEffectWhen == Defined(false))
}
}
}
Expand All @@ -141,7 +141,7 @@ class EffectCombinatorTest extends Test:
effect
}
}.map { result =>
assert(result == Result.fail(Maybe.Empty))
assert(result == Result.fail(Empty))
}
}
"condition is false" in run {
Expand Down
4 changes: 2 additions & 2 deletions kyo-core/jvm/src/main/scala/kyo/Path.scala
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ class Path private (val path: List[String]) derives CanEqual:
Resource.acquireRelease(acquire)(release).map { res =>
readOnce(res).map { state =>
Loop(state) {
case Maybe.Empty => Loop.done(Emit.Ack.Stop)
case Maybe.Defined(content) =>
case Empty => Loop.done(Emit.Ack.Stop)
case Defined(content) =>
Emit.andMap(writeOnce(content)) {
case Emit.Ack.Stop => Loop.done(Emit.Ack.Stop)
case _ => readOnce(res).map(Loop.continue(_))
Expand Down
2 changes: 1 addition & 1 deletion kyo-core/shared/src/main/scala/kyo/Async.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package kyo

import java.util.concurrent.atomic.AtomicInteger
import kyo.Maybe.Empty
import kyo.Empty
import kyo.Result.Panic
import kyo.Tag
import kyo.internal.FiberPlatformSpecific
Expand Down
14 changes: 7 additions & 7 deletions kyo-core/shared/src/main/scala/kyo/Channel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,11 @@ object Channel:
throw closedException
else
u.poll() match
case Maybe.Empty =>
case Empty =>
val p = Promise.Unsafe.init[Nothing, A]()
takes.add(p)
p.safe.get
case Maybe.Defined(v) =>
case Defined(v) =>
v
finally
flush()
Expand All @@ -221,11 +221,11 @@ object Channel:
throw closedException
else
u.poll() match
case Maybe.Empty =>
case Empty =>
val p = Promise.Unsafe.init[Nothing, A]()
takes.add(p)
p.safe
case Maybe.Defined(v) =>
case Defined(v) =>
Fiber.success(v)
finally
flush()
Expand All @@ -248,7 +248,7 @@ object Channel:
def close(using frame: Frame) =
IO.Unsafe {
u.close() match
case Maybe.Empty => Maybe.empty
case Empty => Maybe.empty
case r =>
val c = Result.panic(closedException)
def dropTakes(): Unit =
Expand Down Expand Up @@ -283,11 +283,11 @@ object Channel:
val p = takes.poll()
if !isNull(p) then
u.poll() match
case Maybe.Empty =>
case Empty =>
// If the queue has been emptied before the
// transfer, requeue the consumer's promise.
discard(takes.add(p))
case Maybe.Defined(v) =>
case Defined(v) =>
if !p.complete(Result.success(v)) && !u.offer(v) then
// If completing the take fails and the queue
// cannot accept the value back, enqueue a
Expand Down
2 changes: 1 addition & 1 deletion kyo-core/shared/src/main/scala/kyo/Fiber.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package kyo

export Fiber.Promise
import java.util.concurrent.atomic.AtomicInteger
import kyo.Maybe.Empty
import kyo.Empty
import kyo.Result.Panic
import kyo.Tag
import kyo.internal.FiberPlatformSpecific
Expand Down
Loading

0 comments on commit ddc9ebc

Please sign in to comment.