Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Tagless in Kotlin with Arrow and manual DI
import arrow.*
import arrow.typeclasses.*
import arrow.effects.*
/* algebras */
interface Service1<F> {
fun addOne(fa: Kind<F, Int>): Kind<F, Int>
}
interface Service2<F> {
fun addTwo(fa: Kind<F, Int>): Kind<F, Int>
}
interface App<F> {
fun addAll(fa: Kind<F, Int>): Kind<F, Int>
}
/* interpreters */
class Service1Interpreter<F>(val functor: Functor<F>) : Service1<F>, Functor<F> by functor {
override fun addOne(fa: Kind<F, Int>): Kind<F, Int> =
fa.map { it + 1 }
}
class Service2Interpreter<F>(val functor: Functor<F>) : Service2<F>, Functor<F> by functor {
override fun addTwo(fa: Kind<F, Int>): Kind<F, Int> =
fa.map { it + 2 }
}
class AppInterpreter<F>(
val service1: Service1<F>,
val service2: Service2<F>) : App<F> {
override fun addAll(fa: Kind<F, Int>): Kind<F, Int> =
service2.addTwo(service1.addOne(fa))
}
/* DI module */
class Module<F>(val functor: Functor<F>) {
val service1: Service1<F> = Service1Interpreter(functor)
val service2: Service2<F> = Service2Interpreter(functor)
val app: App<F> = AppInterpreter(service1, service2)
}
/** End of the world **/
object test {
@JvmStatic
fun main(args: Array<String>) {
val ioContext = Module(IO.functor()) // concretion to IO happens at the edge
ioContext.run {
println(app.addAll(IO { 1 }).fix().unsafeRunSync()) //4
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment