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

Complete Async #1198

Merged
merged 72 commits into from
Dec 29, 2018
Merged
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
c869843
add asyncF to Async
JorgeCastilloPrz Nov 22, 2018
70fbde4
up to date
JorgeCastilloPrz Nov 30, 2018
7b6abc5
Add EitherT Bracket & MonadDefer instances
nomisRev Dec 5, 2018
c0a7dc3
Add Async for EitherT. 1 law failing
nomisRev Dec 5, 2018
8b45172
Update instances and add OptionT instances
nomisRev Dec 6, 2018
95e0503
Add instances and fix constraints
nomisRev Dec 6, 2018
93b1df3
Complete instances
nomisRev Dec 8, 2018
20e73a6
Merge remote-tracking branch 'origin/master' into asyncF
nomisRev Dec 9, 2018
5ae0c4d
Add asyncF for IO & AsyncLaws
nomisRev Dec 10, 2018
3e5b78b
fix instances maybe, deferred and single
nomisRev Dec 11, 2018
0f952ff
Missing instances
nomisRev Dec 11, 2018
b9d4cd2
Merge branch 'master' into simon-bracket
nomisRev Dec 12, 2018
1685443
Rx instances
nomisRev Dec 12, 2018
d68e6d1
Update BracketLaws
nomisRev Dec 12, 2018
c91ef21
Add cancellation support to Single Bracket
nomisRev Dec 12, 2018
05475fb
Add cancellation support to Observable bracket
nomisRev Dec 12, 2018
8008a13
Add cancellation support to Maybe bracket
nomisRev Dec 12, 2018
816d35d
Add cancellation support to Flowable bracket
nomisRev Dec 12, 2018
129065d
Add test for IO & make test consistent
nomisRev Dec 12, 2018
0e5f6e4
Merge branch 'simon-bracket' of github.com:arrow-kt/arrow into simon-…
nomisRev Dec 12, 2018
d381b8e
Cleanup
nomisRev Dec 12, 2018
3362300
Remove unused code
nomisRev Dec 12, 2018
d985cf1
Fix detekt
nomisRev Dec 12, 2018
1ece633
FluxK Bracket instance
nomisRev Dec 12, 2018
529e642
Clean up
nomisRev Dec 12, 2018
16564a8
Fix Reactor bracket instances
nomisRev Dec 12, 2018
72abb4e
Fix ObservableK docs
nomisRev Dec 12, 2018
946a085
import arrow.effects.maybek.applicative.applicative
nomisRev Dec 13, 2018
0e49df6
Speed up MonadDeferLaws tests
nomisRev Dec 13, 2018
f3be9de
DeferredK bracket instance
nomisRev Dec 13, 2018
161bee1
Update DeferredK instance to work with Generated & Wrapped
nomisRev Dec 13, 2018
59be4dd
Add documentation
nomisRev Dec 13, 2018
589c96b
Clean up
nomisRev Dec 13, 2018
2580769
Merge branch 'simon-bracket' into asyncF
nomisRev Dec 13, 2018
5714216
DeferredK asyncF
nomisRev Dec 13, 2018
49c9705
ObservableK asyncF
nomisRev Dec 13, 2018
c870532
FlowableK asyncF
nomisRev Dec 13, 2018
b00af27
Add MaybeK asyncF
nomisRev Dec 13, 2018
e06a77e
Add SingleK asyncF
nomisRev Dec 13, 2018
a3ef0fd
Add instances for monad transformers
nomisRev Dec 13, 2018
df4ca94
Add cancellable to Async
nomisRev Dec 13, 2018
fac696e
Fix build and add shift/cancellableF to Async
nomisRev Dec 13, 2018
b3b31c5
Merge branch 'master' into 1124-jc-asyncF
nomisRev Dec 13, 2018
a573bcd
Fix API cancellableF
nomisRev Dec 13, 2018
4757f8b
Merge branch '1124-jc-asyncF' of github.com:arrow-kt/arrow into asyncF
nomisRev Dec 13, 2018
e07c175
Clean up
nomisRev Dec 14, 2018
58c2e5b
Add some documentation for async
nomisRev Dec 14, 2018
d52cc1f
Complete docs Async
nomisRev Dec 14, 2018
42ee4cd
Fix cancelable and fix build
nomisRev Dec 15, 2018
8d76357
Merge branch 'master' into 1124-jc-asyncF
nomisRev Dec 15, 2018
552c108
Clean up and fix cancelable
nomisRev Dec 15, 2018
36c9747
Merge branch '1124-jc-asyncF' of github.com:arrow-kt/arrow into asyncF
nomisRev Dec 15, 2018
a4fa7a8
Merge branch 'master' into 1124-jc-asyncF
raulraja Dec 18, 2018
70285e1
Merge branch 'master' into 1124-jc-asyncF
raulraja Dec 18, 2018
1e13d7b
Merge branch 'master' into 1124-jc-asyncF
raulraja Dec 19, 2018
0069486
Merge branch 'master' into 1124-jc-asyncF
raulraja Dec 19, 2018
0f5e261
Merge remote-tracking branch 'origin/master' into asyncF
nomisRev Dec 22, 2018
58d8cc3
Update docs
nomisRev Dec 22, 2018
34ad18c
Update docs
nomisRev Dec 22, 2018
bd92865
Detekt fix
nomisRev Dec 22, 2018
b7e84a9
Revert access modifier change & remove test file
nomisRev Dec 22, 2018
8b03ef3
Merge branch 'master' into asyncF
nomisRev Dec 23, 2018
abee2f6
Add monoid instance Id
nomisRev Dec 23, 2018
97b7b0b
Cleanup IO instance
nomisRev Dec 23, 2018
2f4ad45
Fix docs
nomisRev Dec 23, 2018
edfa95c
Merge branch 'master' into 1124-jc-asyncF
nomisRev Dec 26, 2018
4f41962
Remove duplicated Id instances
nomisRev Dec 26, 2018
2af7022
Merge branch 'master' into 1124-jc-asyncF
nomisRev Dec 28, 2018
f1a9a97
Fix merge and improve style instances
nomisRev Dec 28, 2018
be30966
Merge branch '1124-jc-asyncF' of github.com:arrow-kt/arrow into asyncF
nomisRev Dec 28, 2018
ddae2ad
Fix code style & remove debug println
nomisRev Dec 28, 2018
cd3f428
Remove unused imports
nomisRev Dec 28, 2018
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package arrow.common.utils
import arrow.common.messager.logE
import arrow.documented
import arrow.meta.encoder.jvm.KotlinMetatadataEncoder
import me.eugeniomarletti.kotlin.metadata.kotlinMetadata
import me.eugeniomarletti.kotlin.metadata.shadow.metadata.deserialization.receiverType
import me.eugeniomarletti.kotlin.processing.KotlinAbstractProcessor
import java.io.File
import java.io.IOException
Expand Down Expand Up @@ -58,8 +60,14 @@ abstract class AbstractProcessor : KotlinAbstractProcessor(), ProcessorUtils, Ko
ElementKind.INTERFACE -> (this as TypeElement).qualifiedName.toString()
ElementKind.METHOD -> (this as ExecutableElement).let {
val name = (it.enclosingElement as TypeElement).qualifiedName.toString()

val extensionName = (it.enclosingElement.kotlinMetadata?.asClassOrPackageDataWrapper(it.enclosingElement as TypeElement) as? ClassOrPackageDataWrapper.Class)?.let { classData ->
val n = classData.getFunction(it).toMeta(classData, it).receiverType?.simpleName
if (n == classData.simpleName) "" else "$n-"
} ?: ""

val functionName = it.simpleName.toString()
"$name.$functionName"
"$name.$extensionName$functionName"
}
else -> knownError("Unsupported @documented $kind")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ interface PolyTemplateGenerator : MetaApi {
private fun String.replaceMonadDeferImports(info: TypeClassInstance): String {
val monadDeferPackageName = PackageName(info.instance.packageName.value +
"." + info.projectedCompanion.simpleName.substringAfterLast(".").toLowerCase() +
".monaddefer")
".monadDefer")
return replace(
"_imports_monaddefer_",
"""
Expand All @@ -133,8 +133,7 @@ interface PolyTemplateGenerator : MetaApi {
|import ${packageName.value.quote()}.*
|import arrow.core.*
|$factoryImports
|$additionalImports
|""".trimMargin()
|$additionalImports""".trimMargin()
)
}

Expand All @@ -152,8 +151,7 @@ interface PolyTemplateGenerator : MetaApi {
val factory = it.returnType?.simpleName?.decapitalize()?.substringBefore("<") ?: ""
val fact = if (factory == "functor") "monad" else factory
"""|import arrow.instances.id.$fact.$fact
|import arrow.core.*
""".trimMargin()
|import arrow.core.*""".trimMargin()
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package arrow.core

import arrow.core.Id
import arrow.instances.eq
import arrow.instances.hash
import arrow.instances.id.applicative.applicative
import arrow.instances.id.comonad.comonad
import arrow.instances.id.eq.eq
import arrow.instances.id.hash.hash
import arrow.instances.id.monad.monad
import arrow.instances.id.monoid.monoid
import arrow.instances.id.show.show
import arrow.instances.id.traverse.traverse
import arrow.instances.id.semigroup.semigroup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ class StateT<F, S, A>(
* @param ff function with the [StateT] context.
*/
fun <B> ap(MF: Monad<F>, ff: StateTOf<F, S, (A) -> B>): StateT<F, S, B> =
ff.fix().map2(MF, this) { f, a -> f(a) }
ff.fix().map2(MF, this) { f: (A) -> B, a: A -> f(a) }

/**
* Create a product of the value types of [StateT].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class KleisliTest : UnitSpec() {

testLaws(
BracketLaws.laws(
BF = Kleisli.bracket<ForIO, Int, Throwable>(IO.bracket()),
Kleisli.bracket<ForIO, Int, Throwable>(IO.bracket()),
EQ = IOEQ(),
EQ_EITHER = IOEitherEQ(),
EQERR = IOEQ()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,41 @@ interface IdShowInstance<A> : Show<Id<A>> {
toString()
}

@extension
interface IdSemigroupInstance<A> : Semigroup<Id<A>> {

fun SA(): Semigroup<A>

override fun Id<A>.combine(b: Id<A>): Id<A> = SA().run {
Id(value().combine(b.value()))
}

}

@extension
interface IdMonoidInstance<A> : Monoid<Id<A>>, IdSemigroupInstance<A> {

fun MA(): Monoid<A>

override fun SA() = MA()

override fun empty(): Id<A> =
Id(MA().empty())

}

@extension
interface IdFunctorInstance : Functor<ForId> {
override fun <A, B> Kind<ForId, A>.map(f: (A) -> B): Id<B> =
override fun <A, B> IdOf<A>.map(f: (A) -> B): Id<B> =
fix().map(f)
}

@extension
interface IdApplicativeInstance : Applicative<ForId> {
override fun <A, B> Kind<ForId, A>.ap(ff: Kind<ForId, (A) -> B>): Id<B> =
override fun <A, B> IdOf<A>.ap(ff: IdOf<(A) -> B>): Id<B> =
fix().ap(ff)

override fun <A, B> Kind<ForId, A>.map(f: (A) -> B): Id<B> =
override fun <A, B> IdOf<A>.map(f: (A) -> B): Id<B> =
fix().map(f)

override fun <A> just(a: A): Id<A> =
Expand All @@ -59,16 +82,16 @@ interface IdApplicativeInstance : Applicative<ForId> {

@extension
interface IdMonadInstance : Monad<ForId> {
override fun <A, B> Kind<ForId, A>.ap(ff: Kind<ForId, (A) -> B>): Id<B> =
override fun <A, B> IdOf<A>.ap(ff: IdOf<(A) -> B>): Id<B> =
fix().ap(ff)

override fun <A, B> Kind<ForId, A>.flatMap(f: (A) -> Kind<ForId, B>): Id<B> =
override fun <A, B> IdOf<A>.flatMap(f: (A) -> IdOf<B>): Id<B> =
fix().flatMap(f)

override fun <A, B> tailRecM(a: A, f: kotlin.Function1<A, IdOf<Either<A, B>>>): Id<B> =
Id.tailRecM(a, f)

override fun <A, B> Kind<ForId, A>.map(f: (A) -> B): Id<B> =
override fun <A, B> IdOf<A>.map(f: (A) -> B): Id<B> =
fix().map(f)

override fun <A> just(a: A): Id<A> =
Expand All @@ -77,46 +100,46 @@ interface IdMonadInstance : Monad<ForId> {

@extension
interface IdComonadInstance : Comonad<ForId> {
override fun <A, B> Kind<ForId, A>.coflatMap(f: (Kind<ForId, A>) -> B): Id<B> =
override fun <A, B> IdOf<A>.coflatMap(f: (IdOf<A>) -> B): Id<B> =
fix().coflatMap(f)

override fun <A> Kind<ForId, A>.extract(): A =
override fun <A> IdOf<A>.extract(): A =
fix().extract()

override fun <A, B> Kind<ForId, A>.map(f: (A) -> B): Id<B> =
override fun <A, B> IdOf<A>.map(f: (A) -> B): Id<B> =
fix().map(f)
}

@extension
interface IdBimonadInstance : Bimonad<ForId> {
override fun <A, B> Kind<ForId, A>.ap(ff: Kind<ForId, (A) -> B>): Id<B> =
override fun <A, B> IdOf<A>.ap(ff: IdOf<(A) -> B>): Id<B> =
fix().ap(ff)

override fun <A, B> Kind<ForId, A>.flatMap(f: (A) -> Kind<ForId, B>): Id<B> =
override fun <A, B> IdOf<A>.flatMap(f: (A) -> IdOf<B>): Id<B> =
fix().flatMap(f)

override fun <A, B> tailRecM(a: A, f: kotlin.Function1<A, IdOf<Either<A, B>>>): Id<B> =
Id.tailRecM(a, f)

override fun <A, B> Kind<ForId, A>.map(f: (A) -> B): Id<B> =
override fun <A, B> IdOf<A>.map(f: (A) -> B): Id<B> =
fix().map(f)

override fun <A> just(a: A): Id<A> =
Id.just(a)

override fun <A, B> Kind<ForId, A>.coflatMap(f: (Kind<ForId, A>) -> B): Id<B> =
override fun <A, B> IdOf<A>.coflatMap(f: (IdOf<A>) -> B): Id<B> =
fix().coflatMap(f)

override fun <A> Kind<ForId, A>.extract(): A =
override fun <A> IdOf<A>.extract(): A =
fix().extract()
}

@extension
interface IdFoldableInstance : Foldable<ForId> {
override fun <A, B> Kind<ForId, A>.foldLeft(b: B, f: (B, A) -> B): B =
override fun <A, B> IdOf<A>.foldLeft(b: B, f: (B, A) -> B): B =
fix().foldLeft(b, f)

override fun <A, B> Kind<ForId, A>.foldRight(lb: Eval<B>, f: (A, Eval<B>) -> Eval<B>): Eval<B> =
override fun <A, B> IdOf<A>.foldRight(lb: Eval<B>, f: (A, Eval<B>) -> Eval<B>): Eval<B> =
fix().foldRight(lb, f)
}

Expand All @@ -129,13 +152,13 @@ fun <A, G> IdOf<Kind<G, A>>.sequence(GA: Applicative<G>): Kind<G, Id<A>> =

@extension
interface IdTraverseInstance : Traverse<ForId> {
override fun <A, B> Kind<ForId, A>.map(f: (A) -> B): Id<B> =
override fun <A, B> IdOf<A>.map(f: (A) -> B): Id<B> =
fix().map(f)

override fun <G, A, B> Kind<ForId, A>.traverse(AP: Applicative<G>, f: (A) -> Kind<G, B>): Kind<G, Id<B>> =
override fun <G, A, B> IdOf<A>.traverse(AP: Applicative<G>, f: (A) -> Kind<G, B>): Kind<G, Id<B>> =
idTraverse(AP, f)

override fun <A, B> Kind<ForId, A>.foldLeft(b: B, f: (B, A) -> B): B =
override fun <A, B> IdOf<A>.foldLeft(b: B, f: (B, A) -> B): B =
fix().foldLeft(b, f)

override fun <A, B> arrow.Kind<arrow.core.ForId, A>.foldRight(lb: arrow.core.Eval<B>, f: (A, arrow.core.Eval<B>) -> arrow.core.Eval<B>): Eval<B> =
Expand All @@ -153,7 +176,7 @@ interface IdHashInstance<A> : Hash<Id<A>>, IdEqInstance<A> {
}

object IdContext : IdBimonadInstance, IdTraverseInstance {
override fun <A, B> Kind<ForId, A>.map(f: (A) -> B): Id<B> =
override fun <A, B> IdOf<A>.map(f: (A) -> B): Id<B> =
fix().map(f)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ interface KleisliMonadErrorInstance<F, D, E> : MonadError<KleisliPartialOf<F, D>
override fun AE(): ApplicativeError<F, E> = ME()

override fun AF(): Applicative<F> = ME()

}

@extension
interface KleisliMonadThrow<F, D> : MonadThrow<KleisliPartialOf<F, D>>, KleisliMonadErrorInstance<F, D, Throwable> {
override fun ME(): MonadError<F, Throwable>
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package arrow.mtl.typeclasses
import arrow.Kind
import arrow.Kind2
import arrow.core.Tuple2
import arrow.instances.statet.applicative.just
import arrow.typeclasses.Alternative
import arrow.typeclasses.Bifoldable
import arrow.typeclasses.Foldable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@ import arrow.Kind
import arrow.core.Either
import arrow.core.Left
import arrow.core.Right
import arrow.effects.IO
import arrow.effects.Promise
import arrow.effects.instances.io.async.defer
import arrow.effects.instances.io.monadDefer.defer
import arrow.effects.typeclasses.Async
import arrow.effects.typeclasses.ExitCase
import arrow.test.generators.genEither
import arrow.test.generators.genIntSmall
import arrow.test.generators.genThrowable
import arrow.typeclasses.Eq
import io.kotlintest.properties.Gen
import io.kotlintest.properties.forAll
import io.kotlintest.properties.map
import kotlinx.coroutines.newSingleThreadContext

object AsyncLaws {
Expand All @@ -26,7 +33,11 @@ object AsyncLaws {
Law("Async Laws: error equivalence") { AC.asyncError(EQERR) },
Law("Async Laws: continueOn jumps threads") { AC.continueOn(EQ) },
Law("Async Laws: async constructor") { AC.asyncConstructor(EQ) },
Law("Async Laws: continueOn on comprehensions") { AC.continueOnComprehension(EQ) }
Law("Async Laws: async can be derived from asyncF") { AC.asyncCanBeDerivedFromAsyncF(EQ) },
Law("Async Laws: bracket release is called on completed or error") { AC.bracketReleaseIscalledOnCompletedOrError(EQ) },
Law("Async Laws: continueOn on comprehensions") { AC.continueOnComprehension(EQ) },
Law("Async Laws: async cancelable coherence") { AC.asyncCancelableCoherence(EQ) },
Law("Async Laws: cancelable cancelableF coherence") { AC.cancelableCancelableFCoherence(EQ) }
)

fun <F> Async<F>.asyncSuccess(EQ: Eq<Kind<F, Int>>): Unit =
Expand Down Expand Up @@ -68,7 +79,46 @@ object AsyncLaws {
}.equalUnderTheLaw(just(threadId1 + threadId2), EQ)
}

// Turns out that kotlinx.coroutines decides to rewrite thread names
private fun getCurrentThread() =
Thread.currentThread().name.substringBefore(' ').toInt()
}
fun <F> Async<F>.asyncCanBeDerivedFromAsyncF(EQ: Eq<Kind<F, Int>>): Unit =
forAll(genEither(genThrowable(), Gen.int())) { eith ->
val k: ((Either<Throwable, Int>) -> Unit) -> Unit = { f ->
f(eith)
}

async(k).equalUnderTheLaw(asyncF { cb -> delay { k(cb) } }, EQ)
}

fun <F> Async<F>.bracketReleaseIscalledOnCompletedOrError(EQ: Eq<Kind<F, Int>>): Unit =
forAll(Gen.string().map(::just), Gen.int()) { fa, b ->
Promise.uncancelable<F, Int>(this).flatMap { promise ->
val br = delay { promise }.bracketCase(use = { fa }, release = { r, exitCase ->
when (exitCase) {
is ExitCase.Completed -> r.complete(b)
is ExitCase.Error -> r.complete(b)
else -> just(Unit)
}
})

asyncF<Unit> { cb ->
br.flatMap { delay { cb(Right(Unit)) } }
}.flatMap { promise.get }
}.equalUnderTheLaw(just(b), EQ)
}

fun <F> Async<F>.asyncCancelableCoherence(EQ: Eq<Kind<F, Int>>): Unit =
forAll(genEither(genThrowable(), Gen.int())) { eith ->
async<Int> { cb -> cb(eith) }
.equalUnderTheLaw(cancelable { cb -> cb(eith); just(Unit) }, EQ)
}

fun <F> Async<F>.cancelableCancelableFCoherence(EQ: Eq<Kind<F, Int>>): Unit =
forAll(genEither(genThrowable(), Gen.int())) { eith ->
cancelable<Int> { cb -> cb(eith); just(Unit) }
.equalUnderTheLaw(cancelableF { cb -> delay { cb(eith); just(Unit) } }, EQ)
}

// Turns out that kotlinx.coroutines decides to rewrite thread names
private fun getCurrentThread() =
Thread.currentThread().name.substringBefore(' ').toInt()

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ interface Applicative<F> : Functor<F> {

fun <A> just(a: A): Kind<F, A>

fun <A> A.just(dummy: Unit = Unit): Kind<F, A> = just(this)
fun <A> A.just(dummy: Unit = Unit): Kind<F, A> =
just(this)

fun unit(): Kind<F, Unit> = just(Unit)

Expand All @@ -22,11 +23,14 @@ interface Applicative<F> : Functor<F> {
fun <A, B> Kind<F, A>.product(fb: Kind<F, B>): Kind<F, Tuple2<A, B>> =
fb.ap(this.map { a: A -> { b: B -> Tuple2(a, b) } })

override fun <A, B> Kind<F, A>.map(f: (A) -> B): Kind<F, B> = ap(just(f))
override fun <A, B> Kind<F, A>.map(f: (A) -> B): Kind<F, B> =
ap(just(f))

fun <A, B, Z> Kind<F, A>.map2(fb: Kind<F, B>, f: (Tuple2<A, B>) -> Z): Kind<F, Z> = product(fb).map(f)
fun <A, B, Z> Kind<F, A>.map2(fb: Kind<F, B>, f: (Tuple2<A, B>) -> Z): Kind<F, Z> =
product(fb).map(f)

fun <A, B, Z> Kind<F, A>.map2Eval(fb: Eval<Kind<F, B>>, f: (Tuple2<A, B>) -> Z): Eval<Kind<F, Z>> = fb.map { fc -> map2(fc, f) }
fun <A, B, Z> Kind<F, A>.map2Eval(fb: Eval<Kind<F, B>>, f: (Tuple2<A, B>) -> Z): Eval<Kind<F, Z>> =
fb.map { fc -> map2(fc, f) }

fun <A, B, Z> Kind<F, Tuple2<A, B>>.product(
other: Kind<F, Z>,
Expand Down
Loading