Skip to content

Commit

Permalink
Rework Fx constructors (#185)
Browse files Browse the repository at this point in the history
* Use an object to allow default suspend fx constructor and better discovery for eager one

* Relocate fx constructors

Co-authored-by: Simon Vergauwen <nomisRev@users.noreply.github.com>
  • Loading branch information
aballano and nomisRev authored Jul 23, 2020
1 parent 462fc81 commit f15701f
Show file tree
Hide file tree
Showing 14 changed files with 216 additions and 161 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import arrow.higherkind
import arrow.typeclasses.Applicative
import arrow.typeclasses.Semigroup
import arrow.typeclasses.Show
import arrow.typeclasses.suspended.BindSyntax
import kotlin.coroutines.Continuation
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn

fun <A, T> ConstOf<A, T>.value(): A = this.fix().value()

Expand Down Expand Up @@ -52,36 +49,3 @@ fun <T, A, G> ConstOf<A, Kind<G, T>>.sequence(GA: Applicative<G>): Kind<G, Const

inline fun <A> A.const(): Const<A, Nothing> =
Const(this)

fun <A, T> const(c: suspend EagerBind<ConstPartialOf<A>>.() -> A): Const<A, T> {
val continuation: ConstContinuation<A, A> = ConstContinuation()
return continuation.startCoroutineUninterceptedAndReturn {
Const.just(c())
} as Const<A, T>
}

suspend fun <A, T> const(c: suspend BindSyntax<ConstPartialOf<A>>.() -> A): Const<A, T> =
suspendCoroutineUninterceptedOrReturn { cont ->
val continuation = ConstSContinuation(cont as Continuation<ConstOf<A, T>>)
continuation.startCoroutineUninterceptedOrReturn {
Const.just(c())
}
}

internal class ConstSContinuation<A, T>(
parent: Continuation<ConstOf<A, T>>
) : SuspendMonadContinuation<ConstPartialOf<A>, T>(parent) {
override fun ShortCircuit.recover(): Const<A, T> =
throw this

override suspend fun <B> Kind<ConstPartialOf<A>, B>.bind(): B =
value() as B
}

internal class ConstContinuation<A, T> : MonadContinuation<ConstPartialOf<A>, T>() {
override fun ShortCircuit.recover(): Const<A, T> =
throw this

override suspend fun <B> Kind<ConstPartialOf<A>, B>.bind(): B =
value() as B
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import arrow.core.Either.Left
import arrow.core.Either.Right
import arrow.higherkind
import arrow.typeclasses.Show
import arrow.typeclasses.suspended.BindSyntax
import kotlin.coroutines.Continuation
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn

/**
*
Expand Down Expand Up @@ -646,7 +643,7 @@ import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
*
* ```kotlin:ank:playground
* import arrow.core.Either
* import arrow.core.either
* import arrow.core.computations.either
*
* suspend fun main() {
* val value =
Expand All @@ -673,7 +670,6 @@ import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
* ```
*
*/

@higherkind
sealed class Either<out A, out B> : EitherOf<A, B> {

Expand Down Expand Up @@ -1081,8 +1077,6 @@ inline fun <A, B> B?.rightIfNotNull(default: () -> A): Either<A, B> = when (this
/**
* Returns [Either.Right] if the value of type Any? is null, otherwise the specified A value wrapped into an
* [Either.Left].
*
* ```
*/
inline fun <A> Any?.rightIfNull(default: () -> A): Either<A, Nothing?> = when (this) {
null -> Either.right(null)
Expand All @@ -1100,36 +1094,3 @@ inline fun <A, B> EitherOf<A, B>.handleErrorWith(f: (A) -> EitherOf<A, B>): Eith
is Right -> it
}
}

fun <E, A> either(c: suspend EagerBind<EitherPartialOf<E>>.() -> A): Either<E, A> {
val continuation: EitherContinuation<E, A> = EitherContinuation()
return continuation.startCoroutineUninterceptedAndReturn {
Right(c())
} as Either<E, A>
}

suspend fun <E, A> either(c: suspend BindSyntax<EitherPartialOf<E>>.() -> A): Either<E, A> =
suspendCoroutineUninterceptedOrReturn { cont ->
val continuation = EitherSContinuation(cont as Continuation<EitherOf<E, A>>)
continuation.startCoroutineUninterceptedOrReturn {
Right(c())
}
}

internal class EitherSContinuation<E, A>(
parent: Continuation<EitherOf<E, A>>
) : SuspendMonadContinuation<EitherPartialOf<E>, A>(parent) {
override fun ShortCircuit.recover(): Kind<EitherPartialOf<E>, A> =
Left(value as E)

override suspend fun <A> Kind<EitherPartialOf<E>, A>.bind(): A =
fix().fold({ e -> throw ShortCircuit(e) }, ::identity)
}

internal class EitherContinuation<E, A> : MonadContinuation<EitherPartialOf<E>, A>() {
override fun ShortCircuit.recover(): Kind<EitherPartialOf<E>, A> =
Left(value as E)

override suspend fun <A> Kind<EitherPartialOf<E>, A>.bind(): A =
fix().fold({ e -> throw ShortCircuit(e) }, ::identity)
}
37 changes: 0 additions & 37 deletions arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/Eval.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package arrow.core

import arrow.Kind
import arrow.higherkind
import arrow.typeclasses.suspended.BindSyntax
import kotlin.coroutines.Continuation
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn

fun <A> EvalOf<A>.value(): A = this.fix().value()

Expand Down Expand Up @@ -367,36 +363,3 @@ fun <A, B> Iterator<A>.iterateRight(lb: Eval<B>, f: (A, Eval<B>) -> Eval<B>): Ev
Eval.defer { if (this.hasNext()) f(this.next(), loop()) else lb }
return loop()
}

fun <A> eval(c: suspend EagerBind<ForEval>.() -> A): Eval<A> {
val continuation: EvalContinuation<A> = EvalContinuation()
return continuation.startCoroutineUninterceptedAndReturn {
Eval.just(c())
} as Eval<A>
}

suspend fun <A> eval(c: suspend BindSyntax<ForEval>.() -> A): Eval<A> =
suspendCoroutineUninterceptedOrReturn { cont ->
val continuation = EvalSContinuation(cont as Continuation<EvalOf<A>>)
continuation.startCoroutineUninterceptedOrReturn {
Eval.just(c())
}
}

internal class EvalSContinuation<A>(
parent: Continuation<EvalOf<A>>
) : SuspendMonadContinuation<ForEval, A>(parent) {
override fun ShortCircuit.recover(): Kind<ForEval, A> =
throw this

override suspend fun <A> Kind<ForEval, A>.bind(): A =
fix().value()
}

internal class EvalContinuation<A> : MonadContinuation<ForEval, A>() {
override fun ShortCircuit.recover(): Kind<ForEval, A> =
throw this

override suspend fun <A> Kind<ForEval, A>.bind(): A =
fix().value()
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import arrow.higherkind
import arrow.typeclasses.Applicative
import arrow.typeclasses.Semigroup
import arrow.typeclasses.Show
import arrow.typeclasses.suspended.BindSyntax
import kotlin.coroutines.Continuation
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn

typealias ValidatedNel<E, A> = Validated<Nel<E>, A>
typealias Valid<A> = Validated.Valid<A>
Expand Down Expand Up @@ -142,7 +139,7 @@ typealias Invalid<E> = Validated.Invalid<E>
* import arrow.core.Option
* import arrow.core.Some
* import arrow.core.Validated
* import arrow.core.validated
* import arrow.core.computations.validated
* import arrow.core.valid
* import arrow.core.invalid
*
Expand Down Expand Up @@ -244,7 +241,7 @@ typealias Invalid<E> = Validated.Invalid<E>
* import arrow.core.Option
* import arrow.core.Some
* import arrow.core.Validated
* import arrow.core.validated
* import arrow.core.computations.validated
* import arrow.core.valid
* import arrow.core.invalid
* import arrow.core.NonEmptyList
Expand Down Expand Up @@ -311,7 +308,7 @@ typealias Invalid<E> = Validated.Invalid<E>
* import arrow.core.Option
* import arrow.core.Some
* import arrow.core.Validated
* import arrow.core.validated
* import arrow.core.computations.validated
* import arrow.core.valid
* import arrow.core.invalid
* import arrow.core.NonEmptyList
Expand Down Expand Up @@ -385,7 +382,7 @@ typealias Invalid<E> = Validated.Invalid<E>
* import arrow.core.right
* import arrow.core.Some
* import arrow.core.Validated
* import arrow.core.validated
* import arrow.core.computations.validated
* import arrow.core.valid
* import arrow.core.invalid
*
Expand Down Expand Up @@ -914,36 +911,3 @@ inline fun <A> A.validNel(): ValidatedNel<Nothing, A> =

inline fun <E> E.invalidNel(): ValidatedNel<E, Nothing> =
Validated.invalidNel(this)

fun <E, A> validated(c: suspend EagerBind<ValidatedPartialOf<E>>.() -> A): Validated<E, A> {
val continuation: ValidatedContinuation<E, A> = ValidatedContinuation()
return continuation.startCoroutineUninterceptedAndReturn {
Valid(c())
} as Validated<E, A>
}

suspend fun <E, A> validated(c: suspend BindSyntax<ValidatedPartialOf<E>>.() -> A): Validated<E, A> =
suspendCoroutineUninterceptedOrReturn { cont ->
val continuation = ValidatedSContinuation(cont as Continuation<ValidatedOf<E, A>>)
continuation.startCoroutineUninterceptedOrReturn {
Valid(c())
}
}

internal class ValidatedSContinuation<E, A>(
parent: Continuation<ValidatedOf<E, A>>
) : SuspendMonadContinuation<ValidatedPartialOf<E>, A>(parent) {
override suspend fun <A> Kind<ValidatedPartialOf<E>, A>.bind(): A =
fix().fold({ e -> throw ShortCircuit(e) }, ::identity)

override fun ShortCircuit.recover(): Kind<ValidatedPartialOf<E>, A> =
Invalid(value as E)
}

internal class ValidatedContinuation<E, A> : MonadContinuation<ValidatedPartialOf<E>, A>() {
override suspend fun <A> Kind<ValidatedPartialOf<E>, A>.bind(): A =
fix().fold({ e -> throw ShortCircuit(e) }, ::identity)

override fun ShortCircuit.recover(): Kind<ValidatedPartialOf<E>, A> =
Invalid(value as E)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package arrow.core.computations

import arrow.Kind
import arrow.core.Const
import arrow.core.ConstOf
import arrow.core.ConstPartialOf
import arrow.core.EagerBind
import arrow.core.MonadContinuation
import arrow.core.ShortCircuit
import arrow.core.SuspendMonadContinuation
import arrow.core.value
import arrow.typeclasses.suspended.BindSyntax
import kotlin.coroutines.Continuation
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn

object const {
fun <A, T> eager(c: suspend EagerBind<ConstPartialOf<A>>.() -> A): Const<A, T> {
val continuation: ConstContinuation<A, A> = ConstContinuation()
return continuation.startCoroutineUninterceptedAndReturn {
Const.just(c())
} as Const<A, T>
}

suspend operator fun <A, T> invoke(c: suspend BindSyntax<ConstPartialOf<A>>.() -> A): Const<A, T> =
suspendCoroutineUninterceptedOrReturn { cont ->
val continuation = ConstSContinuation(cont as Continuation<ConstOf<A, T>>)
continuation.startCoroutineUninterceptedOrReturn {
Const.just(c())
}
}

internal class ConstSContinuation<A, T>(
parent: Continuation<ConstOf<A, T>>
) : SuspendMonadContinuation<ConstPartialOf<A>, T>(parent) {
override fun ShortCircuit.recover(): Const<A, T> =
throw this

override suspend fun <B> Kind<ConstPartialOf<A>, B>.bind(): B =
value() as B
}

internal class ConstContinuation<A, T> : MonadContinuation<ConstPartialOf<A>, T>() {
override fun ShortCircuit.recover(): Const<A, T> =
throw this

override suspend fun <B> Kind<ConstPartialOf<A>, B>.bind(): B =
value() as B
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package arrow.core.computations

import arrow.Kind
import arrow.core.EagerBind
import arrow.core.Either
import arrow.core.EitherOf
import arrow.core.EitherPartialOf
import arrow.core.MonadContinuation
import arrow.core.ShortCircuit
import arrow.core.SuspendMonadContinuation
import arrow.core.fix
import arrow.core.identity
import arrow.typeclasses.suspended.BindSyntax
import kotlin.coroutines.Continuation
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn

object either {
fun <E, A> eager(c: suspend EagerBind<EitherPartialOf<E>>.() -> A): Either<E, A> {
val continuation: EitherContinuation<E, A> = EitherContinuation()
return continuation.startCoroutineUninterceptedAndReturn {
Either.Right(c())
} as Either<E, A>
}

suspend operator fun <E, A> invoke(c: suspend BindSyntax<EitherPartialOf<E>>.() -> A): Either<E, A> =
suspendCoroutineUninterceptedOrReturn { cont ->
val continuation = EitherSContinuation(cont as Continuation<EitherOf<E, A>>)
continuation.startCoroutineUninterceptedOrReturn {
Either.Right(c())
}
}

internal class EitherSContinuation<E, A>(
parent: Continuation<EitherOf<E, A>>
) : SuspendMonadContinuation<EitherPartialOf<E>, A>(parent) {
override fun ShortCircuit.recover(): Kind<EitherPartialOf<E>, A> =
Either.Left(value as E)

override suspend fun <A> Kind<EitherPartialOf<E>, A>.bind(): A =
fix().fold({ e -> throw ShortCircuit(e) }, ::identity)
}

internal class EitherContinuation<E, A> : MonadContinuation<EitherPartialOf<E>, A>() {
override fun ShortCircuit.recover(): Kind<EitherPartialOf<E>, A> =
Either.Left(value as E)

override suspend fun <A> Kind<EitherPartialOf<E>, A>.bind(): A =
fix().fold({ e -> throw ShortCircuit(e) }, ::identity)
}
}
Loading

0 comments on commit f15701f

Please sign in to comment.