Skip to content

Instantly share code, notes, and snippets.

@raulraja
Last active June 17, 2018 12:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raulraja/4844dffca27c3689b47ea970ed5e276d to your computer and use it in GitHub Desktop.
Save raulraja/4844dffca27c3689b47ea970ed5e276d to your computer and use it in GitHub Desktop.
Tagless with Arrow & typeclassless using extension functions and instances
import arrow.Kind
import arrow.core.Option
import arrow.core.Try
import arrow.core.functor
import arrow.effects.IO
import arrow.effects.fix
import arrow.effects.functor
import arrow.typeclasses.Functor
/* algebras */
interface Service1<F> : Functor<F> {
fun Kind<F, Int>.addOne(): Kind<F, Int> =
map { it + 1 }
}
interface Service2<F> : Functor<F> {
fun Kind<F, Int>.addTwo(): Kind<F, Int> =
map { it + 2 }
}
interface App<F> : Service1<F>, Service2<F> {
fun Kind<F, Int>.addThree(): Kind<F, Int> =
addOne().addTwo()
}
/* Our ap works for all functors */
val <F> Functor<F>.app: App<F>
get() = object : App<F> {
override fun <A, B> Kind<F, A>.map(f: (A) -> B): Kind<F, B> = this@app.run { map(f) }
}
/** End of the world **/
object test {
@JvmStatic
fun main(args: Array<String>) {
Option.functor().app.run { Option(1).addThree() }.let(::println) //Some(4)
Try.functor().app.run { Try { 1 }.addThree() }.let(::println) //Success(value=4)
IO.functor().app.run { IO { 1 }.addThree().fix().unsafeRunSync() }.let(::println) //4
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment