Effects

Effects are abstractions that help us to encapsulate non-deterministic operations such as network requests or disk I/O. These types of operations don't fit as nicely into the pure mathematical model of functional programming because they take time, and their result is non-deterministic.

Arrow provides several abstractions with which we can model our side effect code:

Using IO, we can define a long-running operation and then consume it using typeclasses such as attempt() or runAsync():

IO<Int> {
Thread.sleep(2000)
5
}
.runAsync { result ->
result.fold({ IO { println("Error") } }, { IO { println("$it") } })
}.unsafeRunAsync { }

Here, we see an example of how we can define an IO operation, map both result states to desired outputs, and then evaluate the entire flow with unsafeRunAsync{ }.

Using Arrow, we can write type-safe, highly functional code with Kotlin. This code will maintain the desirable aspects of functional programming, such as immutability and pure functions, while providing standard mechanisms for side effects that are often required for modern applications. Arrow provides integrations for libraries such as Rx or Kotlin coroutines, meaning that it can be integrated with your existing code as well.

This section has just scratched the surface of using Arrow for functional Kotlin programming, but should help you to understand the key concepts and how to learn more.