Skip to content

Instantly share code, notes, and snippets.

@fteychene
Last active October 14, 2020 09:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fteychene/53803ccb668711672bce476bcd45d2e7 to your computer and use it in GitHub Desktop.
Save fteychene/53803ccb668711672bce476bcd45d2e7 to your computer and use it in GitHub Desktop.
Arrow fx coroutine play on Chuck Norris facts
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.10'
}
apply plugin: 'kotlin-kapt'
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
jcenter()
maven { url "https://dl.bintray.com/arrow-kt/arrow-kt/" }
maven { url 'https://oss.jfrog.org/artifactory/oss-snapshot-local/' } // for SNAPSHOT builds
}
def arrow_version = "0.11.0"
def fuel_version = "2.3.0"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "io.arrow-kt:arrow-core:$arrow_version"
implementation "io.arrow-kt:arrow-fx:$arrow_version"
implementation "io.arrow-kt:arrow-fx-coroutines:$arrow_version"
implementation "io.arrow-kt:arrow-optics:$arrow_version"
implementation "io.arrow-kt:arrow-syntax:$arrow_version"
kapt "io.arrow-kt:arrow-meta:$arrow_version"
implementation "com.github.kittinunf.fuel:fuel:$fuel_version"
implementation "com.github.kittinunf.fuel:fuel-jackson:$fuel_version"
implementation "com.github.kittinunf.fuel:fuel-coroutines:$fuel_version"
implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.11.+"
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
jvmTarget = "1.8"
}
}
import arrow.core.*
import arrow.core.extensions.either.applicative.applicative
import arrow.core.extensions.either.applicative.map
import arrow.core.extensions.list.traverse.sequence
import arrow.core.extensions.listk.functor.functor
import arrow.fx.IODispatchers.IOPool
import arrow.fx.coroutines.ComputationPool
import arrow.fx.coroutines.evalOn
import arrow.fx.coroutines.parTraverse
import arrow.typeclasses.Show
import com.github.kittinunf.fuel.core.awaitResponseResult
import com.github.kittinunf.fuel.httpGet
import com.github.kittinunf.fuel.jackson.jacksonDeserializerOf
suspend fun printThreadName(): Unit =
println(Thread.currentThread().name)
data class HttpError(val message: String, val cause: Throwable?)
typealias Category = String
suspend fun loadCategories(): Either<HttpError, List<Category>> =
evalOn(IOPool) {
val (value, error) = "https://api.chucknorris.io/jokes/categories"
.httpGet()
.awaitResponseResult(jacksonDeserializerOf<List<String>>()).third
printThreadName()
error
?.let { Either.left(HttpError("Error loading categories", it)) }
?: Either.right(value!!)
}
data class Quote(
val value: String
)
suspend fun loadRandom(category: String): Either<HttpError, Quote> =
evalOn(IOPool) {
val (value, error) = "https://api.chucknorris.io/jokes/random?category=$category"
.httpGet()
.awaitResponseResult(jacksonDeserializerOf<Quote>()).third
printThreadName()
error
?.let { Either.left(HttpError("Error loading quote for $category", it)) }
?: Either.right(value!!)
}
suspend fun loadQuotesForCategories(categories: List<Category>): Either<HttpError, List<Pair<Category, Quote>>> =
run {
printThreadName()
categories.parTraverse { category -> loadRandom(category).map { category to it } }
.sequence(Either.applicative()).map { it.fix() }.fix()
}
val categoryQuoteShow = object : Show<Pair<Category, Quote>> {
override fun Pair<Category, Quote>.show(): String =
"$first - ${second.value}"
}
val showList = with(categoryQuoteShow) {
ListK.functor().lift<Pair<Category, Quote>, String> { it.show() }
}
suspend fun main() {
evalOn(ComputationPool) {
printThreadName()
loadCategories()
.flatMap { loadQuotesForCategories(it) }
.map { showList.invoke(it.k()).fix() }
.map {
printThreadName()
it.forEach(::println)
}
}
}
@fteychene
Copy link
Author

Output sample

ForkJoinPool-1-worker-19
io-arrow-kt-worker-0
ForkJoinPool-1-worker-19
io-arrow-kt-worker-10
io-arrow-kt-worker-15
io-arrow-kt-worker-13
io-arrow-kt-worker-7
io-arrow-kt-worker-5
io-arrow-kt-worker-1
io-arrow-kt-worker-4
io-arrow-kt-worker-9
io-arrow-kt-worker-12
io-arrow-kt-worker-6
io-arrow-kt-worker-2
io-arrow-kt-worker-11
io-arrow-kt-worker-14
io-arrow-kt-worker-3
io-arrow-kt-worker-8
io-arrow-kt-worker-0
ForkJoinPool-1-worker-23
animal -  Chuck Norris once rode a nine foot grizzly bear through an automatic car wash, instead of taking a shower.
career -  Chuck Norris is actually the front man for Apple. He let's Steve Jobs run the show when he's on a mission. Chuck Norris is always on a mission.
celebrity -  Chuck Norris smells what the Rock is cooking... because the Rock is Chuck Norris' personal chef.
dev -  Chuck Norris does not code in cycles, he codes in strikes.
explicit -  Chuck Norris' penis can bench over 250.
fashion -  Chuck Norris does not follow fashion trends, they follow him. But then he turns around and kicks their ass. Nobody follows Chuck Norris.
food -  For Chuck Norris, there are only two food groups. Steak and beer.
history -  Chuck Norris once shot down a German fighter plane with his finger. By yelling "Bang!"
money -  Well it's-a one for the money, two for the show, three to get ready and BAM!! Chuck Norris.
movie -  Jean-Claude Van Damme once kicked Chuck Norris' ass. He was then awakened from his dream by a roundhouse kick to the face.
music -  Most boots are made for walkin'. Chuck Norris' boots ain't that merciful.
political -  Chuck Norris is widely predicted to be first black president. If you're thinking to yourself, "But Chuck Norris isn't black", then you are dead wrong. And stop being a racist.
religion -  It's widely believed that Jesus was Chuck Norris' stunt double for crucifixion due to the fact that it is impossible for nails to pierce Chuck Norris' skin.
science -  Chuck Norris describes human beings as "a sociable holder for blood and guts".
sport -  Chuck Norris was banned from competitive bullriding after a 1992 exhibition in San Antonio, when he rode the bull 1,346 miles from Texas to Milwaukee Wisconsin to pick up his dry cleaning.
travel -  Chuck Norris did in fact, build Rome in a day.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment