Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Error handling with Kotlin and Arrow

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Fedy Salah Fedy Salah
September 11, 2020

Functional Error handling with Kotlin and Arrow

Avatar for Fedy Salah

Fedy Salah

September 11, 2020

Other Decks in Technology

Transcript

  1. #JSC2020 Fedy Salah @fedysalah Basics Fault : incorrect internal state

    Error : visibly incorrect behaviour Failure : main functionality is broken Fault => Error => Failure
  2. #JSC2020 Fedy Salah @fedysalah Say no more! Exceptions to the

    rescue BusinessException javax.validation ExceptionMapper (JEE) @ExceptionHandler (Spring)
  3. #JSC2020 Fedy Salah @fedysalah Exceptions downside Break referential transparency (RT)

    Not type-safe Feel more like a GOTO jumping back to the caller Not reliable, throwing exception may not survive an async block
  4. #JSC2020 Fedy Salah @fedysalah Exceptions downside Incorrect and dangerous code

    Throwable is an open hierarchy where you may catch more than you originally intended to Costly to create. Throwable#fillInStackTrace attempts to gather all stack information to present you with a meaningful stacktrace ref: http://normanmaurer.me/blog/2013/11/09/The-hidden-performance-costs-of-instantiating-Throwables
  5. #JSC2020 Fedy Salah @fedysalah Exceptions In FP Exceptions may be

    considered generally a poor choice in FP when - Modeling absence - Modeling known business cases that result in alternate paths - Used in async boundaries over APIs (callbacks) But of course you can still have exceptions when you try to access servers that are down or files that are missing
  6. #JSC2020 Fedy Salah @fedysalah Λrrow Vavr (formerly called Javaslang) for

    Java Λrrow (0.11.0) is a library for Typed Functional Programming in Kotlin Λrrow includes the most popular data types, type classes and abstractions such Option, Either, IO, Functor, Applicative, Monad Ref: https://arrow-kt.io/
  7. #JSC2020 Fedy Salah @fedysalah Monad Monad is a concept, an

    abstract interface, that simply defines a way of composing data When data type supports composition (flatMap), that's pretty much everything that is needed to wear the "monad badge"
  8. #JSC2020 Fedy Salah @fedysalah Option<T> Null is bad (NullPointerException) Kotlin

    tries to solve the problem with Null-safety based on ? (not functional) Modeling the absence of values through Option (Scala, Haskell) When Option type is used, consumer will be forced to handle the case of absent value Λrrow provides a Monad instance for Option
  9. #JSC2020 Fedy Salah @fedysalah Either<L,R> Either represents the presence of

    either a Left value or a Right value Good substitute for BusinessException Λrrow provides a Monad instance for Either in the same way it did for Option When computing over Either, whenever a Left value is found, the computation short-circuits
  10. #JSC2020 Fedy Salah @fedysalah Validated Λrrow provides Monad instance for

    Validated Parallel or Sequential Validation Validated are used to accumulate errors vs Either to short-circuit a computation upon the first error
  11. #JSC2020 Fedy Salah @fedysalah Monad Comprehension To solve this structural

    problem, Kotlin language introduced Coroutines Javascript generators (async/await), Continuation (Java/Loom) Using coroutines, Λrrow provides a specialization that enables readable async/ await style code for any Monad Internally, Monad#flatMap is used for chaining Same as for comprehension in Scala
  12. #JSC2020 Fedy Salah @fedysalah More... Effects + Effects Comprehension (async)

    ListK, SetK, MapK Monad comprehension over Flux/Mono (FluxK/MonoK) Monad comprehension over Rx (ObservableK) What if Rx + Either ? Oh shoot, it sounds complicated !
  13. #JSC2020 Fedy Salah @fedysalah Monad Transformers Because monads don’t compose,

    we may end up with nested structures such Monad Transformers can help us to reduce this boilerplate Cats / ScalaZ (Scala) Monad Transformers enable you to combine two monads into a super monad
  14. #JSC2020 Fedy Salah @fedysalah OptionT OptionT has the form of

    OptionT<F, A> Any monad F surrounding an Option<A>, we can obtain an OptionT<F, A> So our specialization OptionT<ForMonoK, String> is the OptionT transformer around values that are of MonoK<Option<String>>.
  15. #JSC2020 Fedy Salah @fedysalah EitherT EitherT has the form of

    EitherT<F, L, A> Any monad F surrounding an Either<L, A>, we can obtain an EitherT<F, L, A> So our specialization EitherT<ForMonoK, BookingError, A> is the EitherT transformer around values that are of MonoK<Either<BookingError, A>>.
  16. #JSC2020 Fedy Salah @fedysalah Performances ? The hand-coded version is

    1.5x faster than EitherT for short tasks For long tasks, the differences are probably too small (~10%) to make any practical difference unless performance is your main concern. In that case, stay away from this combination. Ref: https://www.iteratorshq.com/blog/benchmarking-functional-error-handling-in-scala/ Method ns/op (tf = 2) ns/op (tf = 5) ns/op (tf = 100) ns/op (tf = 200) EitherT 9681 (+- 14) 9871 (+- 8) 29288 (+- 41) 48674 (+- 99) Future[Either[…]] 6443 (+- 11) 6775 (+- 21) 26657 (+- 42) 45970 (+- 66)
  17. #JSC2020 Fedy Salah @fedysalah Conclusion Λrrow and Monad transformers everywhere

    ? For me Exceptions are for lazy people (I’ll deal with it later , or may be never...) Faults and errors happens all the time, make your system more fault tolerant The more your code is explicit, the easier for others to maintain it