Skip to content

Instantly share code, notes, and snippets.

@pakoito
Created April 8, 2018 11:24
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 pakoito/68e343cadc11f173d24fc4058bcb8d16 to your computer and use it in GitHub Desktop.
Save pakoito/68e343cadc11f173d24fc4058bcb8d16 to your computer and use it in GitHub Desktop.
Applicatives, Functors and Monads using Kotlin and Arrow
import arrow.core.*
import arrow.data.k
import arrow.syntax.applicative.tupled
import arrow.syntax.functor.map
import arrow.typeclasses.binding
typealias IntFunction = (Int) -> Int
fun IntFunction.map(g: IntFunction) = { it: Int -> this(g(it)) }
object Main {
@JvmStatic
fun main(args: Array<String>) {
with (Option.monad()) {
mapOverOption()
mapOverFunction()
applicative()
applicativeList()
tripleProduct()
halfMonad()
}
}
fun Functor<ForOption>.mapOverOption() {
println(Some(2).map { it + 3 })
val none: Option<Int> = none()
println(none.map { it + 3})
println(listOf(Some(3), None).map { it.map { it + 3} })
}
fun Functor<ForOption>.mapOverFunction() {
val add3 = { it: Int -> it + 3 }
val double = { it: Int -> it * 2 }
println(double.map(add3)(3))
}
fun Applicative<ForOption>.applicative() {
val add3: Option<(Int) -> Int> = Some({ it: Int -> it + 3 })
val result = tupled(add3, Some(3)).map { it.a(it.b)}
val result2 = Some(3).ap(Some<(Int)->Int>({ it -> it + 2}))
println(result)
println(result2)
}
fun Applicative<ForOption>.applicativeList() {
val add3 = { it: Int -> it + 3 }
val double = { it: Int -> it * 2 }
val result = listOf(2,3).k().ap(listOf<(Int)->Int>({it + 3}, {it * 2}).k())
println(result)
}
fun Applicative<ForOption>.tripleProduct() {
println(tupled(Some(2), Some(3), Some(4)).map { it.a * it.b * it.c })
println(tupled(Some(2), none(), Some(4)).map { it.a * it.b * it.c })
}
fun Monad<ForOption>.halfMonad() {
val half = { n: Int -> if (n % 2 == 0) Some(n/2) else None}
println(half(5))
println(half(6))
fun Monad<ForOption>.monadComprehension(o: Option<Int>) =
binding {
val a = o.bind()
val b = half(a).bind()
b
}
println(monadComprehension(Some(5)))
println(monadComprehension(Some(6)))
println(monadComprehension(None))
// alternative approach
println(Some(5).flatMap(half))
println(Some(6).flatMap(half))
println(None.flatMap(half))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment