From ddc9ebce6e7c2e8cef97557ec51ab2d4e97d0a0a Mon Sep 17 00:00:00 2001 From: Flavio Brasil Date: Tue, 8 Oct 2024 20:03:59 -0700 Subject: [PATCH] data: export Maybe.Empty and Maybe.Defined to the kyo package --- .../src/main/scala/kyo/Combinators.scala | 53 +++++++++---------- .../src/main/scala/kyo/Constructors.scala | 12 ++--- .../test/scala/kyo/AbortCombinatorTest.scala | 32 +++++------ .../src/test/scala/kyo/ConstructorsTest.scala | 16 +++--- .../test/scala/kyo/EffectCombinatorTest.scala | 6 +-- kyo-core/jvm/src/main/scala/kyo/Path.scala | 4 +- .../shared/src/main/scala/kyo/Async.scala | 2 +- .../shared/src/main/scala/kyo/Channel.scala | 14 ++--- .../shared/src/main/scala/kyo/Fiber.scala | 2 +- .../shared/src/main/scala/kyo/Meter.scala | 8 +-- .../shared/src/main/scala/kyo/Queue.scala | 4 +- .../shared/src/main/scala/kyo/Resource.scala | 4 +- .../shared/src/main/scala/kyo/System.scala | 8 +-- .../src/test/scala/kyo/ResourceTest.scala | 2 +- .../src/test/scala/kyo/SystemTest.scala | 8 +-- .../scala/kyo/scheduler/IOPromiseTest.scala | 30 +++++------ .../shared/src/main/scala/kyo/Maybe.scala | 3 ++ .../src/test/scala/kyo/DirectTest.scala | 2 +- .../shared/src/main/scala/kyo/Abort.scala | 14 ++--- .../shared/src/main/scala/kyo/Memo.scala | 4 +- .../shared/src/test/scala/kyo/AbortTest.scala | 4 +- .../shared/src/test/scala/kyo/EnvTest.scala | 8 +-- 22 files changed, 121 insertions(+), 119 deletions(-) diff --git a/kyo-combinators/shared/src/main/scala/kyo/Combinators.scala b/kyo-combinators/shared/src/main/scala/kyo/Combinators.scala index b7cfb1015..fb264702c 100644 --- a/kyo-combinators/shared/src/main/scala/kyo/Combinators.scala +++ b/kyo-combinators/shared/src/main/scala/kyo/Combinators.scala @@ -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. * @@ -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. @@ -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 } @@ -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)) @@ -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 @@ -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]]) } diff --git a/kyo-combinators/shared/src/main/scala/kyo/Constructors.scala b/kyo-combinators/shared/src/main/scala/kyo/Constructors.scala index b8b10525d..6c9183e64 100644 --- a/kyo-combinators/shared/src/main/scala/kyo/Constructors.scala +++ b/kyo-combinators/shared/src/main/scala/kyo/Constructors.scala @@ -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]. diff --git a/kyo-combinators/shared/src/test/scala/kyo/AbortCombinatorTest.scala b/kyo-combinators/shared/src/test/scala/kyo/AbortCombinatorTest.scala index ad9f30e98..7a05aca63 100644 --- a/kyo-combinators/shared/src/test/scala/kyo/AbortCombinatorTest.scala +++ b/kyo-combinators/shared/src/test/scala/kyo/AbortCombinatorTest.scala @@ -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 { @@ -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)) @@ -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]() diff --git a/kyo-combinators/shared/src/test/scala/kyo/ConstructorsTest.scala b/kyo-combinators/shared/src/test/scala/kyo/ConstructorsTest.scala index 1025a1f3a..7cb510272 100644 --- a/kyo-combinators/shared/src/test/scala/kyo/ConstructorsTest.scala +++ b/kyo-combinators/shared/src/test/scala/kyo/ConstructorsTest.scala @@ -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)) } } diff --git a/kyo-combinators/shared/src/test/scala/kyo/EffectCombinatorTest.scala b/kyo-combinators/shared/src/test/scala/kyo/EffectCombinatorTest.scala index df8559a1b..261ce0ce2 100644 --- a/kyo-combinators/shared/src/test/scala/kyo/EffectCombinatorTest.scala +++ b/kyo-combinators/shared/src/test/scala/kyo/EffectCombinatorTest.scala @@ -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 { @@ -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)) } } } @@ -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 { diff --git a/kyo-core/jvm/src/main/scala/kyo/Path.scala b/kyo-core/jvm/src/main/scala/kyo/Path.scala index bd81cae88..3582fee87 100644 --- a/kyo-core/jvm/src/main/scala/kyo/Path.scala +++ b/kyo-core/jvm/src/main/scala/kyo/Path.scala @@ -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(_)) diff --git a/kyo-core/shared/src/main/scala/kyo/Async.scala b/kyo-core/shared/src/main/scala/kyo/Async.scala index a34e04921..cbaf44595 100644 --- a/kyo-core/shared/src/main/scala/kyo/Async.scala +++ b/kyo-core/shared/src/main/scala/kyo/Async.scala @@ -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 diff --git a/kyo-core/shared/src/main/scala/kyo/Channel.scala b/kyo-core/shared/src/main/scala/kyo/Channel.scala index 5874c5a27..ae9308752 100644 --- a/kyo-core/shared/src/main/scala/kyo/Channel.scala +++ b/kyo-core/shared/src/main/scala/kyo/Channel.scala @@ -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() @@ -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() @@ -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 = @@ -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 diff --git a/kyo-core/shared/src/main/scala/kyo/Fiber.scala b/kyo-core/shared/src/main/scala/kyo/Fiber.scala index c31d340d3..ee5d42e7e 100644 --- a/kyo-core/shared/src/main/scala/kyo/Fiber.scala +++ b/kyo-core/shared/src/main/scala/kyo/Fiber.scala @@ -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 diff --git a/kyo-core/shared/src/main/scala/kyo/Meter.scala b/kyo-core/shared/src/main/scala/kyo/Meter.scala index a87ca9801..24079d34a 100644 --- a/kyo-core/shared/src/main/scala/kyo/Meter.scala +++ b/kyo-core/shared/src/main/scala/kyo/Meter.scala @@ -94,7 +94,7 @@ object Meter: def tryRun[A, S](v: => A < S)(using Frame) = IO.Unsafe { chan.unsafePoll match - case Maybe.Empty => Maybe.empty + case Empty => Maybe.empty case _ => IO.ensure(release) { v.map(Maybe(_)) @@ -125,7 +125,7 @@ object Meter: def tryRun[A, S](v: => A < S)(using Frame) = chan.poll.map { - case Maybe.Empty => + case Empty => Maybe.empty case _ => v.map(Maybe(_)) @@ -217,8 +217,8 @@ object Meter: if idx == meters.length then v.map(Maybe(_)) else meters(idx).tryRun(loop(idx + 1)).map { - case Maybe.Empty => Maybe.empty - case r => r.flatten + case Empty => Maybe.empty + case r => r.flatten } loop() end tryRun diff --git a/kyo-core/shared/src/main/scala/kyo/Queue.scala b/kyo-core/shared/src/main/scala/kyo/Queue.scala index 3102b9568..dabb0b453 100644 --- a/kyo-core/shared/src/main/scala/kyo/Queue.scala +++ b/kyo-core/shared/src/main/scala/kyo/Queue.scala @@ -118,8 +118,8 @@ object Queue: @tailrec def loop(): Unit = val v = poll() v match - case Maybe.Empty => - case Maybe.Defined(v) => + case Empty => + case Defined(v) => b += v loop() end match diff --git a/kyo-core/shared/src/main/scala/kyo/Resource.scala b/kyo-core/shared/src/main/scala/kyo/Resource.scala index ae129a7b5..d26da01e7 100644 --- a/kyo-core/shared/src/main/scala/kyo/Resource.scala +++ b/kyo-core/shared/src/main/scala/kyo/Resource.scala @@ -83,9 +83,9 @@ object Resource: val finalizer = Finalizer(frame, q) def close: Unit < IO = q.close.map { - case Maybe.Empty => + case Empty => bug("Resource finalizer queue already closed.") - case Maybe.Defined(l) => + case Defined(l) => Kyo.foreachDiscard(l)(task => Abort.run[Throwable](task) .map(_.fold(ex => Log.error("Resource finalizer failed", ex.exception))(_ => ())) diff --git a/kyo-core/shared/src/main/scala/kyo/System.scala b/kyo-core/shared/src/main/scala/kyo/System.scala index 7a4283752..4c633f722 100644 --- a/kyo-core/shared/src/main/scala/kyo/System.scala +++ b/kyo-core/shared/src/main/scala/kyo/System.scala @@ -42,14 +42,14 @@ object System: def env[E, A](name: String)(using p: Parser[E, A], frame: Frame): Maybe[A] < (Abort[E] & IO) = IO.Unsafe { u.env(name) match - case Maybe.Empty => Maybe.Empty - case Maybe.Defined(v) => Abort.get(p(v).map(Maybe(_))) + case Empty => Empty + case Defined(v) => Abort.get(p(v).map(Maybe(_))) } def property[E, A](name: String)(using p: Parser[E, A], frame: Frame): Maybe[A] < (Abort[E] & IO) = IO.Unsafe { u.property(name) match - case Maybe.Empty => Maybe.Empty - case Maybe.Defined(v) => Abort.get(p(v).map(Maybe(_))) + case Empty => Empty + case Defined(v) => Abort.get(p(v).map(Maybe(_))) } def lineSeparator(using Frame): String < IO = IO.Unsafe(u.lineSeparator()) def userName(using Frame): String < IO = IO.Unsafe(u.userName()) diff --git a/kyo-core/shared/src/test/scala/kyo/ResourceTest.scala b/kyo-core/shared/src/test/scala/kyo/ResourceTest.scala index 9186b41cc..8a559fe78 100644 --- a/kyo-core/shared/src/test/scala/kyo/ResourceTest.scala +++ b/kyo-core/shared/src/test/scala/kyo/ResourceTest.scala @@ -181,7 +181,7 @@ class ResourceTest extends Test: .pipe(Resource.run) .pipe(Async.runAndBlock(timeout)) .pipe(Abort.run[Timeout](_)) - .pipe(Abort.run[Maybe.Empty](_)) + .pipe(Abort.run[Empty](_)) .map { _ => assert(closes == 1) } diff --git a/kyo-core/shared/src/test/scala/kyo/SystemTest.scala b/kyo-core/shared/src/test/scala/kyo/SystemTest.scala index ca45ee49f..19164431b 100644 --- a/kyo-core/shared/src/test/scala/kyo/SystemTest.scala +++ b/kyo-core/shared/src/test/scala/kyo/SystemTest.scala @@ -309,9 +309,9 @@ class SystemTest extends Test: assert(testUnsafe.env(TEST_ENV) == Maybe("test_env_value")) } - "should return Maybe.Empty for non-existent environment variable" in { + "should return Empty for non-existent environment variable" in { val testUnsafe = new TestUnsafeSystem() - assert(testUnsafe.env("NON_EXISTENT_ENV") == Maybe.Empty) + assert(testUnsafe.env("NON_EXISTENT_ENV") == Empty) } "should get system property correctly" in { @@ -319,9 +319,9 @@ class SystemTest extends Test: assert(testUnsafe.property(TEST_PROP) == Maybe("test_prop_value")) } - "should return Maybe.Empty for non-existent system property" in { + "should return Empty for non-existent system property" in { val testUnsafe = new TestUnsafeSystem() - assert(testUnsafe.property("NON_EXISTENT_PROP") == Maybe.Empty) + assert(testUnsafe.property("NON_EXISTENT_PROP") == Empty) } "should get line separator correctly" in { diff --git a/kyo-core/shared/src/test/scala/kyo/scheduler/IOPromiseTest.scala b/kyo-core/shared/src/test/scala/kyo/scheduler/IOPromiseTest.scala index 3fc97d015..4e6d994b2 100644 --- a/kyo-core/shared/src/test/scala/kyo/scheduler/IOPromiseTest.scala +++ b/kyo-core/shared/src/test/scala/kyo/scheduler/IOPromiseTest.scala @@ -300,7 +300,7 @@ class IOPromiseTest extends Test: val masked = original.mask var originalCompleted = false - var maskedResult: Maybe[Result[Nothing, Int]] = Maybe.Empty + var maskedResult: Maybe[Result[Nothing, Int]] = Empty original.onComplete(_ => originalCompleted = true) masked.onComplete(r => maskedResult = Maybe(r)) @@ -314,7 +314,7 @@ class IOPromiseTest extends Test: val original = new IOPromise[Nothing, Int]() val masked = original.mask - var maskedResult: Maybe[Result[Nothing, Int]] = Maybe.Empty + var maskedResult: Maybe[Result[Nothing, Int]] = Empty masked.onComplete(r => maskedResult = Maybe(r)) original.complete(Result.success(42)) @@ -325,7 +325,7 @@ class IOPromiseTest extends Test: val original = new IOPromise[Exception, Int]() val masked = original.mask - var maskedResult: Maybe[Result[Exception, Int]] = Maybe.Empty + var maskedResult: Maybe[Result[Exception, Int]] = Empty masked.onComplete(r => maskedResult = Maybe(r)) val ex = new Exception("Test exception") @@ -337,8 +337,8 @@ class IOPromiseTest extends Test: val original = new IOPromise[Nothing, Int]() val masked = original.mask - var originalResult: Maybe[Result[Nothing, Int]] = Maybe.Empty - var maskedResult: Maybe[Result[Nothing, Int]] = Maybe.Empty + var originalResult: Maybe[Result[Nothing, Int]] = Empty + var maskedResult: Maybe[Result[Nothing, Int]] = Empty original.onComplete(r => originalResult = Maybe(r)) masked.onComplete(r => maskedResult = Maybe(r)) @@ -355,7 +355,7 @@ class IOPromiseTest extends Test: var originalCompleted = false var masked1Completed = false - var masked2Result: Maybe[Result[Nothing, Int]] = Maybe.Empty + var masked2Result: Maybe[Result[Nothing, Int]] = Empty original.onComplete(_ => originalCompleted = true) masked1.onComplete(_ => masked1Completed = true) @@ -375,7 +375,7 @@ class IOPromiseTest extends Test: original.complete(Result.success(42)) val masked = original.mask - var maskedResult: Maybe[Result[Nothing, Int]] = Maybe.Empty + var maskedResult: Maybe[Result[Nothing, Int]] = Empty masked.onComplete(r => maskedResult = Maybe(r)) assert(maskedResult.contains(Result.success(42))) @@ -385,8 +385,8 @@ class IOPromiseTest extends Test: val original = new IOPromise[Nothing, Int]() val masked = original.mask - var originalResult: Maybe[Result[Nothing, Int]] = Maybe.Empty - var maskedResult: Maybe[Result[Nothing, Int]] = Maybe.Empty + var originalResult: Maybe[Result[Nothing, Int]] = Empty + var maskedResult: Maybe[Result[Nothing, Int]] = Empty original.onComplete(r => originalResult = Maybe(r)) masked.onComplete(r => maskedResult = Maybe(r)) @@ -402,9 +402,9 @@ class IOPromiseTest extends Test: val masked1 = original.mask val masked2 = masked1.mask - var originalResult: Maybe[Result[Nothing, Int]] = Maybe.Empty - var masked1Result: Maybe[Result[Nothing, Int]] = Maybe.Empty - var masked2Result: Maybe[Result[Nothing, Int]] = Maybe.Empty + var originalResult: Maybe[Result[Nothing, Int]] = Empty + var masked1Result: Maybe[Result[Nothing, Int]] = Empty + var masked2Result: Maybe[Result[Nothing, Int]] = Empty original.onComplete(r => originalResult = Maybe(r)) masked1.onComplete(r => masked1Result = Maybe(r)) @@ -428,9 +428,9 @@ class IOPromiseTest extends Test: val masked = original.mask val other = new IOPromise[Nothing, Int]() - var originalResult: Maybe[Result[Nothing, Int]] = Maybe.Empty - var maskedResult: Maybe[Result[Nothing, Int]] = Maybe.Empty - var otherResult: Maybe[Result[Nothing, Int]] = Maybe.Empty + var originalResult: Maybe[Result[Nothing, Int]] = Empty + var maskedResult: Maybe[Result[Nothing, Int]] = Empty + var otherResult: Maybe[Result[Nothing, Int]] = Empty original.onComplete(r => originalResult = Maybe(r)) masked.onComplete(r => maskedResult = Maybe(r)) diff --git a/kyo-data/shared/src/main/scala/kyo/Maybe.scala b/kyo-data/shared/src/main/scala/kyo/Maybe.scala index a784f3c37..7820973dd 100644 --- a/kyo-data/shared/src/main/scala/kyo/Maybe.scala +++ b/kyo-data/shared/src/main/scala/kyo/Maybe.scala @@ -10,6 +10,9 @@ import Maybe.internal.* */ opaque type Maybe[+A] >: (Empty | Defined[A]) = Empty | Defined[A] +export Maybe.Defined +export Maybe.Empty + /** Companion object for Maybe type */ object Maybe: inline given [A, B](using inline ce: CanEqual[A, B]): CanEqual[Maybe[A], Maybe[B]] = CanEqual.derived diff --git a/kyo-direct/shared/src/test/scala/kyo/DirectTest.scala b/kyo-direct/shared/src/test/scala/kyo/DirectTest.scala index 63222ae14..4a2aa50e7 100644 --- a/kyo-direct/shared/src/test/scala/kyo/DirectTest.scala +++ b/kyo-direct/shared/src/test/scala/kyo/DirectTest.scala @@ -40,7 +40,7 @@ class DirectTest extends Test: } "two effects" in run { - val io: String < (IO & Abort[Maybe.Empty]) = + val io: String < (IO & Abort[Empty]) = defer { val a = await(Abort.get(Some("hello"))) val b = await(IO("world")) diff --git a/kyo-prelude/shared/src/main/scala/kyo/Abort.scala b/kyo-prelude/shared/src/main/scala/kyo/Abort.scala index 265620321..826543b8d 100644 --- a/kyo-prelude/shared/src/main/scala/kyo/Abort.scala +++ b/kyo-prelude/shared/src/main/scala/kyo/Abort.scala @@ -91,16 +91,16 @@ object Abort: case Right(value) => value case Left(value) => fail(value) - /** Lifts an Option into the Abort effect with Maybe.Empty as the failure value. + /** Lifts an Option into the Abort effect with Empty as the failure value. * * @param opt * The Option to lift * @return - * A computation that succeeds with the Some value or fails with Maybe.Empty + * A computation that succeeds with the Some value or fails with Empty */ - inline def apply[A](opt: Option[A])(using inline frame: Frame): A < Abort[Maybe.Empty] = + inline def apply[A](opt: Option[A])(using inline frame: Frame): A < Abort[Empty] = opt match - case None => fail(Maybe.Empty) + case None => fail(Empty) case Some(v) => v /** Lifts a scala.util.Try into the Abort effect. @@ -133,11 +133,11 @@ object Abort: * @param m * The Maybe to lift * @return - * A computation that succeeds with the Defined value or fails with Maybe.Empty + * A computation that succeeds with the Defined value or fails with Empty */ @targetName("maybe") - inline def apply[A](m: Maybe[A])(using inline frame: Frame): A < Abort[Maybe.Empty] = - m.fold(fail(Maybe.Empty))(identity) + inline def apply[A](m: Maybe[A])(using inline frame: Frame): A < Abort[Empty] = + m.fold(fail(Empty))(identity) end GetOps /** Operations for lifting various types into the Abort effect. diff --git a/kyo-prelude/shared/src/main/scala/kyo/Memo.scala b/kyo-prelude/shared/src/main/scala/kyo/Memo.scala index 9f9255b0b..fe4a10107 100644 --- a/kyo-prelude/shared/src/main/scala/kyo/Memo.scala +++ b/kyo-prelude/shared/src/main/scala/kyo/Memo.scala @@ -47,9 +47,9 @@ object Memo: input => Var.use[Cache] { cache => cache.get(input, id) match - case Maybe.Defined(cached) => + case Defined(cached) => cached.asInstanceOf[B] - case Maybe.Empty => + case Empty => f(input).map { result => Var.update[Cache](_.updated(input, id, result)) .map(_ => result) diff --git a/kyo-prelude/shared/src/test/scala/kyo/AbortTest.scala b/kyo-prelude/shared/src/test/scala/kyo/AbortTest.scala index d38447211..7f8af341d 100644 --- a/kyo-prelude/shared/src/test/scala/kyo/AbortTest.scala +++ b/kyo-prelude/shared/src/test/scala/kyo/AbortTest.scala @@ -90,11 +90,11 @@ class AbortsTest extends Test: assert(Abort.run(Abort.get(Result.fail(ex1))).eval == Result.fail(ex1)) } "option" in { - assert(Abort.run(Abort.get(Option.empty)).eval == Result.fail(Maybe.Empty)) + assert(Abort.run(Abort.get(Option.empty)).eval == Result.fail(Empty)) assert(Abort.run(Abort.get(Some(1))).eval == Result.success(1)) } "maybe" in { - assert(Abort.run(Abort.get(Maybe.empty)).eval == Result.fail(Maybe.Empty)) + assert(Abort.run(Abort.get(Maybe.empty)).eval == Result.fail(Empty)) assert(Abort.run(Abort.get(Maybe(1))).eval == Result.success(1)) } } diff --git a/kyo-prelude/shared/src/test/scala/kyo/EnvTest.scala b/kyo-prelude/shared/src/test/scala/kyo/EnvTest.scala index 7f834e5d0..f43a7f34e 100644 --- a/kyo-prelude/shared/src/test/scala/kyo/EnvTest.scala +++ b/kyo-prelude/shared/src/test/scala/kyo/EnvTest.scala @@ -142,9 +142,9 @@ class EnvTest extends Test: "effectful services" - { trait Service1: - def apply(i: Int): Int < Abort[Maybe.Empty] + def apply(i: Int): Int < Abort[Empty] trait Service2: - def apply(i: Int): Int < Abort[Maybe.Empty] + def apply(i: Int): Int < Abort[Empty] val service1 = new Service1: def apply(i: Int) = i match @@ -179,7 +179,7 @@ class EnvTest extends Test: Env.get[Service1].map(_(1)).map { i => Env.get[Service2].map(_(i)) } - val v: Int < (Env[Service1] & Env[Service2] & Abort[Maybe.Empty]) = a + val v: Int < (Env[Service1] & Env[Service2] & Abort[Empty]) = a "same handling order" in { val b = Env.run(service2)(v) val c = Env.run(service1)(b) @@ -195,7 +195,7 @@ class EnvTest extends Test: ) } "dependent services" in { - val v2: Int < (Env[Service2] & Abort[Maybe.Empty]) = Env.run(service1)(v) + val v2: Int < (Env[Service2] & Abort[Empty]) = Env.run(service1)(v) assert( Abort.run(Env.run(service2)(v2)).eval == Result.success(3)