- Creating computation DSL by weaving suspend functions: https://kotlinlang.slack.com/archives/C5UPMM0A0/p1631326397023700
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import arrow.core.continuations.EffectScope | |
import arrow.core.continuations.effect | |
object EndOfLine | |
interface Console { | |
context(EffectScope<EndOfLine>) | |
suspend fun read(): String | |
suspend fun String.write(): Unit |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import kotlin.contracts.ExperimentalContracts | |
import kotlin.contracts.InvocationKind | |
import kotlin.contracts.contract | |
import kotlin.time.ExperimentalTime | |
import kotlin.time.measureTimedValue | |
interface Logging { | |
fun info(msg: String): Unit | |
companion object Default : Logging { | |
override fun info(msg: String) = println("INFO: $msg") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import io.ktor.client.HttpClient | |
import io.ktor.client.call.body | |
import io.ktor.client.engine.cio.CIO | |
import io.ktor.client.request.get | |
import io.ktor.client.request.headers | |
import io.ktor.http.HttpHeaders | |
import io.ktor.http.HttpMethod | |
import io.ktor.http.HttpStatusCode | |
import io.ktor.server.application.call | |
import io.ktor.server.application.Application |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ./gradlew runs tests for all configured Apple targets | |
val appleTest = tasks.create("appleTest") | |
subprojects { | |
afterEvaluate { | |
val appleTargets = setOf("tvos", "watchos", "ios", "macos") | |
extensions.findByType<org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension>() | |
?.sourceSets | |
?.filter { appleTargets.any { target -> it.name.contains(target) } && it.name.contains("Test") } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* In Arrow we only provide functions up to arity-9, | |
* using Tuple we can easily compose up to arity-n. | |
* | |
* A small example to show Validated#zip for arity-18 | |
*/ | |
fun validated(): ValidatedNel<String, Int> = | |
"example".invalidNel() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import arrow.core.Either | |
import arrow.core.computations.EitherEffect | |
import arrow.core.computations.either | |
import kotlinx.coroutines.Dispatchers | |
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction | |
typealias Query<E, A> = suspend () -> Either<E, A> | |
fun <E, A> query(f: suspend EitherEffect<E, *>.() -> A): Query<E, A> = | |
suspend { either(f) } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import arrow.core.identity | |
import kotlin.coroutines.Continuation | |
import kotlin.coroutines.resume | |
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn | |
import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn | |
import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED | |
interface ContEffect<R, A> { | |
suspend fun <B> shift(r: R): B |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The DSL uses the suspension system, but the Restricted version uses @RestrictSuspension. | |
This disallows any suspend function to be called inside the DSL except for the functions defined inside RestrictOptionEffect. | |
This means that the DSL can be evaluated immediately, or eagerly. Instead of requiring suspend. | |
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-restricts-suspension/ | |
If you’re already inside a suspend context then it makes most sense to just use the suspend version. That’ll also allow you to use other suspending code inside the DSL |
In Kotlin there is the concept of “co-pure”. The Kotlin compiler has a powerful inliner, which is very commonly used in Kotlin. An inliner takes the code from an inline fun, and puts it in the place of the call-site. So if an inline fun is pure in it’s definition, and it takes a lambda then the resulting code is pure if and only if the passed lambda is also pure. Otherwise the resulting code is impure. So the whether the resulting code pure or not depends 100% on the passed lambda.
fun pureExample(): Unit =
listOf(1, 2, 3).map { it + 1 } // [2, 3, 4] & pure