Skip to content
This repository has been archived by the owner on Feb 24, 2021. It is now read-only.

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
2 people authored and tapegram committed Jul 23, 2020
1 parent 78d8c11 commit c4f1fda
Show file tree
Hide file tree
Showing 14 changed files with 216 additions and 161 deletions.
36 changes: 0 additions & 36 deletions arrow-core-data/src/main/kotlin/arrow/core/Const.kt
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
}
41 changes: 1 addition & 40 deletions arrow-core-data/src/main/kotlin/arrow/core/Either.kt
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 @@ -1096,8 +1092,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 @@ -1115,36 +1109,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-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()
}
44 changes: 4 additions & 40 deletions arrow-core-data/src/main/kotlin/arrow/core/Validated.kt
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)
}
49 changes: 49 additions & 0 deletions arrow-core-data/src/main/kotlin/arrow/core/computations/const.kt
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
}
}
50 changes: 50 additions & 0 deletions arrow-core-data/src/main/kotlin/arrow/core/computations/either.kt
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 c4f1fda

Please sign in to comment.