Skip to content

Instantly share code, notes, and snippets.

@hoc081098
Last active April 12, 2021 08:36
Show Gist options
  • Save hoc081098/1eb4283df49a59798ee47df7550c34ee to your computer and use it in GitHub Desktop.
Save hoc081098/1eb4283df49a59798ee47df7550c34ee to your computer and use it in GitHub Desktop.
@file:Suppress("RedundantSuspendModifier")
import arrow.core.Either
import arrow.core.computations.either
import arrow.fx.coroutines.parTraverseEitherN
import kotlinx.coroutines.delay
import java.io.IOException
import kotlin.time.ExperimentalTime
import kotlin.time.TimeSource
suspend fun throwToTest(id: String) =
if (id == "post#5") throw IOException("Failed to fetch post with id=$id ...") else Unit
data class User(val id: String, val username: String, val postIds: List<String>)
data class Post(val id: String, val title: String)
sealed interface Error {
val cause: Throwable
data class RemoteError(override val cause: Throwable) : Error
data class LocalError(override val cause: Throwable) : Error
}
suspend fun putStrLn(message: Any?) = println(message)
suspend fun fetchUser(userId: String): Either<Error.RemoteError, User> = Either.catch {
putStrLn("fetchUser userId=$userId")
delay(500)
User(
id = userId,
username = "Username",
postIds = List(32) { "post#$it" }
)
}.mapLeft(Error::RemoteError)
suspend fun fetchPost(postId: String): Either<Error.RemoteError, Post> = Either.catch {
putStrLn("fetchPost postId=$postId")
throwToTest(postId)
delay(500)
Post(id = postId, title = "Title of $postId")
}.mapLeft(Error::RemoteError)
suspend fun savePosts(posts: List<Post>): Either<Error.LocalError, Unit> = Either.catch {
delay(500)
putStrLn("Saved ${posts.size}")
}.mapLeft(Error::LocalError)
suspend fun program(userId: String): Either<Error, List<Post>> = either {
val user: User = fetchUser(userId).bind()
val posts: List<Post> = user.postIds.parTraverseEitherN(4, ::fetchPost).bind()
savePosts(posts).bind()
posts
}
@OptIn(ExperimentalTime::class)
suspend fun main() {
val mark = TimeSource.Monotonic.markNow()
program("user#01").fold(ifLeft = { putStrLn("Failure: $it") }, ifRight = { putStrLn("Success: ${it.size}") })
putStrLn(mark.elapsedNow())
}
// build.gradle.kts
//
// plugins {
// kotlin("jvm") version "1.5.0-M2"
// application
// }
//
// dependencies {
// val arrowVersion = "0.13.1"
// implementation("io.arrow-kt:arrow-core:$arrowVersion")
// implementation("io.arrow-kt:arrow-fx-coroutines:$arrowVersion")
// implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3")
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment