Skip to content

Commit

Permalink
Rename MonadSuspend to MonadDefer
Browse files Browse the repository at this point in the history
  • Loading branch information
pakoito committed Apr 7, 2018
1 parent 9508281 commit d8977fd
Show file tree
Hide file tree
Showing 16 changed files with 42 additions and 42 deletions.
4 changes: 2 additions & 2 deletions modules/docs/arrow-docs/docs/_data/menu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ options:
- title: IO
url: /docs/effects/io/

- title: MonadSuspend
url: /docs/effects/monadsuspend/
- title: MonadDefer
url: /docs/effects/monaddefer/

- title: Async
url: /docs/effects/async/
Expand Down
2 changes: 1 addition & 1 deletion modules/docs/arrow-docs/docs/docs/effects/async/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ IO.async()
}.fix().attempt().unsafeRunSync()
```

`Async` includes all combinators present in [`MonadSuspend`]({{ '/docs/effects/monadsuspend/' | relative_url }}).
`Async` includes all combinators present in [`MonadDefer`]({{ '/docs/effects/monaddefer/' | relative_url }}).

### Main Combinators

Expand Down
2 changes: 1 addition & 1 deletion modules/docs/arrow-docs/docs/docs/effects/io/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,5 +245,5 @@ import arrow.effects.*
import arrow.debug.*

showInstances<ForIO, Throwable>()
// [Applicative, ApplicativeError, Functor, Monad, MonadError, MonadSuspend, Async, Effect]
// [Applicative, ApplicativeError, Functor, Monad, MonadError, MonadDefer, Async, Effect]
```
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
layout: docs
title: Sync
permalink: /docs/effects/monadsuspend/
permalink: /docs/effects/monaddefer/
---

## MonadSuspend
## MonadDefer

`MonadSuspend` is a typeclass representing suspension of execution via functions, allowing for asynchronous and lazy computations.
`MonadDefer` is a typeclass representing suspension of execution via functions, allowing for asynchronous and lazy computations.

`MonadSuspend` includes all combinators present in [`MonadError`]({{ '/docs/typeclasses/monaderror' | relative_url }}).
`MonadDefer` includes all combinators present in [`MonadError`]({{ '/docs/typeclasses/monaderror' | relative_url }}).

### Main Combinators

Expand All @@ -17,25 +17,25 @@ permalink: /docs/effects/monadsuspend/
Receives a function returning `A`. The instance is responsible of evaluating the function lazily.

```kotlin
IO.monadSuspend().invoke { 1 }
IO.monadDefer().invoke { 1 }
```

As it captures exceptions, `invoke()` is the simplest way of wrapping existing synchronous APIs.

```kotlin
fun <F> getSongUrlAsync(SC: MonadSuspend<F> = monadSuspend()) =
fun <F> getSongUrlAsync(SC: MonadDefer<F>) =
SC { getSongUrl() }

val songIO: IOOf<Url> = getSongUrlAsync()
val songDeferred: DeferredKOf<Url> = getSongUrlAsync()
val songIO: IOOf<Url> = getSongUrlAsync(IO.monadDefer())
val songDeferred: DeferredKOf<Url> = getSongUrlAsync(DeferredK.monadDefer())
```

#### defer

Receives a function returning `Kind<F, A>`. The instance is responsible of creating and running the returned datatype lazily.

```kotlin
IO.monadSuspend().suspend { IO.just(1) }
IO.monadDefer().defer { IO.just(1) }
```

This can be used to wrap synchronous APIs that already return the expected datatype, forcing them to be run lazily.
Expand All @@ -46,7 +46,7 @@ Suspends a function returning `Unit`.
Useful in cases like [Monad Comprehension]({{ '/docs/patterns/monadcomprehensions' | relative_url }}) where you'd want to defer the start of the comprehension until the datatype is run without needing to use suspend.

```kotlin
val SC = IO.monadSuspend()
val SC = IO.monadDefer()

val result = SC.binding {
println("Print: now")
Expand Down Expand Up @@ -112,11 +112,11 @@ While there is no wrapping of exceptions, the left side of the [`Either`]({{ '/d

### Laws

Arrow provides [`MonadSuspendLaws`]({{ '/docs/typeclasses/laws#monadsuspendlaws' | relative_url }}) in the form of test cases for internal verification of lawful instances and third party apps creating their own `MonadSuspend` instances.
Arrow provides [`MonadDeferLaws`]({{ '/docs/typeclasses/laws#monaddeferlaws' | relative_url }}) in the form of test cases for internal verification of lawful instances and third party apps creating their own `MonadDefer` instances.

### Data types

The following datatypes in Arrow provide instances that adhere to the `MonadSuspend` typeclass.
The following datatypes in Arrow provide instances that adhere to the `MonadDefer` typeclass.

- [IO]({{ '/docs/effects/io' | relative_url }})
- [ObservableK]({{ '/docs/integrations/rx2' | relative_url }})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,12 @@ recoveryArrowWrapper.unsafeAttemptSync()

`DeferredK` created with `bindingCatch` behave the same way regular `Deferred` do, including cancellation by disposing the subscription.

Note that [`MonadSuspend`]({{ '/docs/effects/monadsuspend' | relative_url }}) provides an alternative to `bindingCatch` called `bindingCancellable` returning a `arrow.Disposable`.
Note that [`MonadDefer`]({{ '/docs/effects/monaddefer' | relative_url }}) provides an alternative to `bindingCatch` called `bindingCancellable` returning a `arrow.Disposable`.
Invoking this `Disposable` causes an `BindingCancellationException` in the chain which needs to be handled by the subscriber, similarly to what `Deferred` does.

```kotlin
val (deferred, unsafeCancel) =
DeferredK.monadSuspend().bindingCancellable {
DeferredK.monadDefer().bindingCancellable {
val userProfile = DeferredK { getUserProfile("123") }.bind()
val friendProfiles = userProfile.friends().map { friend ->
DeferredK { getProfile(friend.id) }.bind()
Expand All @@ -189,5 +189,5 @@ import arrow.effects.*
import arrow.debug.*

showInstances<ForDeferredK, Throwable>()
// [Applicative, ApplicativeError, Functor, Monad, MonadError, MonadSuspend, Async, Effect]
// [Applicative, ApplicativeError, Functor, Monad, MonadError, MonadDefer, Async, Effect]
```
16 changes: 8 additions & 8 deletions modules/docs/arrow-docs/docs/docs/integrations/rx2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,16 @@ subject.value()

### Observable comprehensions

The library provides instances of [`MonadError`]({{ '/docs/typeclasses/monaderror' | relative_url }}) and [`MonadSuspend`]({{ '/docs/effects/monadsuspend' | relative_url }}).
The library provides instances of [`MonadError`]({{ '/docs/typeclasses/monaderror' | relative_url }}) and [`MonadDefer`]({{ '/docs/effects/monaddefer' | relative_url }}).

[`MonadSuspend`]({{ '/docs/effects/async' | relative_url }}) allows you to generify over datatypes that can run asynchronous code. You can use it with `ObservableK` and `FlowableK`.
[`MonadDefer`]({{ '/docs/effects/async' | relative_url }}) allows you to generify over datatypes that can run asynchronous code. You can use it with `ObservableK` and `FlowableK`.

```kotlin
fun <F> getSongUrlAsync(MS: MonadSuspend<F> = monadSuspend()) =
fun <F> getSongUrlAsync(MS: MonadDefer<F>) =
MS { getSongUrl() }

val songObservable: ObservableK<Url> = getSongUrlAsync().fix()
val songFlowable: FlowableK<Url> = getSongUrlAsync().fix()
val songObservable: ObservableKOf<Url> = getSongUrlAsync(ObservableK.monadDefer())
val songFlowable: FlowableKOf<Url> = getSongUrlAsync(FlowableK.monadDefer())
```

[`MonadError`]({{ '/docs/typeclasses/monaderror' | relative_url }}) can be used to start a [Monad Comprehension]({{ '/docs/patterns/monadcomprehensions' | relative_url }}) using the method `bindingCatch`, with all its benefits.
Expand Down Expand Up @@ -131,12 +131,12 @@ val disposable =
disposable.dispose()
```

Note that [`MonadSuspend`]({{ '/docs/effects/monadsuspend' | relative_url }}) provides an alternative to `bindingCatch` called `bindingCancellable` returning a `arrow.Disposable`.
Note that [`MonadDefer`]({{ '/docs/effects/monaddefer' | relative_url }}) provides an alternative to `bindingCatch` called `bindingCancellable` returning a `arrow.Disposable`.
Invoking this `Disposable` causes an `BindingCancellationException` in the chain which needs to be handled by the subscriber, similarly to what `Deferred` does.

```kotlin
val (observable, disposable) =
ObservableK.monadSuspend().bindingCancellable {
ObservableK.monadDefer().bindingCancellable {
val userProfile = Observable.create { getUserProfile("123") }
val friendProfiles = userProfile.friends().map { friend ->
bindAsync(observableAsync) { getProfile(friend.id) }
Expand All @@ -157,5 +157,5 @@ import arrow.effects.*
import arrow.debug.*

showInstances<ForObservableK, Throwable>()
// [Applicative, ApplicativeError, Functor, Monad, MonadError, MonadSuspend, Async, Effect, Foldable, Traverse]
// [Applicative, ApplicativeError, Functor, Monad, MonadError, MonadDefer, Async, Effect, Foldable, Traverse]
```
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ fun getLineLengthAverage(path: FilePath): IO<List<String>> =
Note that `bindIn()`assures that the execution will return to the same thread where the binding started after the `bindIn` block executes.

There is also a version of `bindIn` called `bindDeferredIn` that allows deferred construction.
It's available for `bindingCancellable` comprehensions over instances of [`MonadSuspend`]({{ '/docs/effects/monadsuspend' | relative_url }}).
It's available for `bindingCancellable` comprehensions over instances of [`MonadDefer`]({{ '/docs/effects/monaddefer' | relative_url }}).

### What if I'd like to run multiple operations independently from each other, in a non-sequential way?

Expand All @@ -229,7 +229,7 @@ You can check the section on the [Applicative Builder]({{ '/docs/patterns/applic
### Cancellation and cleanup of resources

In some environments that have resources with their own lifecycle (i.e. Activity in Android development) retaining these values in operations that can run indefinitely may cause large memory leaks and lead to undefined behavior.
As cleanup is important in these restricted environments, any instance of [`MonadSuspend`]({{ '/docs/effects/monadsuspend' | relative_url }}) provides the function `bindingCancellable`, which allows for comprehensions to be finished early by throwing an `BindingCancellationException` at the beginning of the next `bind()` step.
As cleanup is important in these restricted environments, any instance of [`MonadDefer`]({{ '/docs/effects/monaddefer' | relative_url }}) provides the function `bindingCancellable`, which allows for comprehensions to be finished early by throwing an `BindingCancellationException` at the beginning of the next `bind()` step.

```kotlin
val (binding: IO<List<User>>, unsafeCancel: Disposable) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ We will list them by their hierarchy.

Effects provides a hierarchy of typeclasses for lazy and asynchronous execution.

- [`MonadSuspend`]({{ '/docs/effects/monadsuspend/' | relative_url }}) - can evaluate functions lazily
- [`MonadDefer`]({{ '/docs/effects/monaddefer/' | relative_url }}) - can evaluate functions lazily

- [`Async`]({{ '/docs/effects/async/' | relative_url }}) - can be created using an asynchronous callback function

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ data class DeferredK<out A>(val deferred: Deferred<A>) : DeferredKOf<A>, Deferre
fun <A> just(a: A): DeferredK<A> =
CompletableDeferred(a).k()

fun <A> suspend(ctx: CoroutineContext = DefaultDispatcher, start: CoroutineStart = CoroutineStart.LAZY, f: suspend () -> A): DeferredK<A> =
fun <A> defer(ctx: CoroutineContext = DefaultDispatcher, start: CoroutineStart = CoroutineStart.LAZY, f: suspend () -> A): DeferredK<A> =
kotlinx.coroutines.experimental.async(ctx, start) { f() }.k()

fun <A> suspend(ctx: CoroutineContext = DefaultDispatcher, start: CoroutineStart = CoroutineStart.LAZY, fa: () -> DeferredKOf<A>): DeferredK<A> =
fun <A> defer(ctx: CoroutineContext = DefaultDispatcher, start: CoroutineStart = CoroutineStart.LAZY, fa: () -> DeferredKOf<A>): DeferredK<A> =
kotlinx.coroutines.experimental.async(ctx, start) { fa().await() }.k()

operator fun <A> invoke(ctx: CoroutineContext = DefaultDispatcher, start: CoroutineStart = CoroutineStart.DEFAULT, f: () -> A): DeferredK<A> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ interface DeferredKMonadErrorInstance : DeferredKMonadInstance, MonadError<ForDe
@instance(DeferredK::class)
interface DeferredKMonadDeferInstance : DeferredKMonadErrorInstance, MonadDefer<ForDeferredK> {
override fun <A> defer(fa: () -> DeferredKOf<A>): DeferredK<A> =
DeferredK.suspend(fa = fa)
DeferredK.defer(fa = fa)
}

@instance(DeferredK::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ data class FlowableK<A>(val flowable: Flowable<A>) : FlowableKOf<A>, FlowableKKi
Flowable.error<A>(t).k()

operator fun <A> invoke(fa: () -> A): FlowableK<A> =
suspend { just(fa()) }
defer { just(fa()) }

fun <A> suspend(fa: () -> FlowableKOf<A>): FlowableK<A> =
fun <A> defer(fa: () -> FlowableKOf<A>): FlowableK<A> =
Flowable.defer { fa().value() }.k()

fun <A> async(fa: Proc<A>, mode: BackpressureStrategy = BackpressureStrategy.BUFFER): FlowableK<A> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ interface FlowableKMonadDeferInstance :
FlowableKMonadErrorInstance,
MonadDefer<ForFlowableK> {
override fun <A> defer(fa: () -> FlowableKOf<A>): FlowableK<A> =
FlowableK.suspend(fa)
FlowableK.defer(fa)

fun BS(): BackpressureStrategy = BackpressureStrategy.BUFFER
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ data class ObservableK<A>(val observable: Observable<A>) : ObservableKOf<A>, Obs
Observable.error<A>(t).k()

operator fun <A> invoke(fa: () -> A): ObservableK<A> =
suspend { just(fa()) }
defer { just(fa()) }

fun <A> suspend(fa: () -> ObservableKOf<A>): ObservableK<A> =
fun <A> defer(fa: () -> ObservableKOf<A>): ObservableK<A> =
Observable.defer { fa().value() }.k()

fun <A> runAsync(fa: Proc<A>): ObservableK<A> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ interface ObservableKMonadDeferInstance :
ObservableKMonadErrorInstance,
MonadDefer<ForObservableK> {
override fun <A> defer(fa: () -> ObservableKOf<A>): ObservableK<A> =
ObservableK.suspend(fa)
ObservableK.defer(fa)
}

@instance(ObservableK::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ sealed class IO<out A> : IOOf<A> {

internal fun <A, B> mapDefault(t: IOOf<A>, f: (A) -> B): IO<B> = Map(t, f, 0)

operator fun <A> invoke(f: () -> A): IO<A> = suspend { Pure(f()) }
operator fun <A> invoke(f: () -> A): IO<A> = defer { Pure(f()) }

fun <A> suspend(f: () -> IOOf<A>): IO<A> = Suspend(f)
fun <A> defer(f: () -> IOOf<A>): IO<A> = Suspend(f)

fun <A> async(k: Proc<A>): IO<A> =
Async { ff: (Either<Throwable, A>) -> Unit ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ interface IOMonadErrorInstance : IOMonadInstance, MonadError<ForIO, Throwable> {
@instance(IO::class)
interface IOMonadDeferInstance : IOMonadErrorInstance, MonadDefer<ForIO> {
override fun <A> defer(fa: () -> IOOf<A>): IO<A> =
IO.suspend(fa)
IO.defer(fa)

override fun lazy(): IO<Unit> = IO.lazy
}
Expand Down

0 comments on commit d8977fd

Please sign in to comment.