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

Intro to Functional Programming in Android with Kotlin

Intro to Functional Programming in Android with Kotlin

Alberto Ballano

May 23, 2017
Tweet

More Decks by Alberto Ballano

Other Decks in Technology

Transcript

  1. What is Functional Programming? Functional programming is a programming paradigm

    that treats computation as the evaluation of mathematical functions.
  2. Keys of FP -First class and Higher-Order functions -Referential transparency

    -Pure functions -Strict vs Non-Strict evaluation
  3. Keys of FP Eliminating side effects can make it much

    easier to understand and predict the behavior of a program.
  4. Monads A monad is just a monoid in the category

    of endofunctors, what's the problem?
  5. Monads A monad is just a monoid in the category

    of endofunctors, what's the problem?
  6. Monads Monads are wrappers with context for a value. So,

    like contexts, you can have different Monads for different use cases.
  7. Monads Absence Option<T> // None or Some<T> Runtime Exceptions Try<T>

    // Failure<T> or Success<T> Exceptional cases
  8. Monads Absence Option<T> // None or Some<T> Runtime Exceptions Try<T>

    // Failure<T> or Success<T> Exceptional cases Either<L, R> // Left<L> or Right<R>
  9. Handling exceptions with Rx useCase.fetchUser() .onErrorReturn(error -> null) .subscribe(user ->

    { if (user != null) … // Success case else … // Failure case })
  10. Handling exceptions with Rx val userSingle = useCase.fetchUser() .onErrorReturn(error ->

    null) val companySingle = useCase.fetchUserCompany() .onErrorReturn(error -> null)
  11. Handling exceptions with Rx val userSingle = useCase.fetchUser() .onErrorReturn(error ->

    null) val companySingle = useCase.fetchUserCompany() .onErrorReturn(error -> null) userSingle.zip(companySingle, (user, company) -> { if (user != null && company != null) … // Merge them else … // ??? }) .subscribe(userWithCompany -> // Success case)***Kind of
  12. Handling exceptions with Monads // Forget about threading for a

    second :) val userResult: Either<ExceptionCase, User> = … val companyResult: Either<ExceptionCase, Company> = … val userWithCompany = userResult.flatMap { user -> companyResult.map { company -> // Merge them } }
  13. Handling exceptions with Monads // Forget about threading for a

    second :) val userResult: Either<ExceptionCase, User> = … val companyResult: Either<ExceptionCase, Company> = … val userWithCompany = EitherMonad<User>().binding { val user = bind { userResult } val company = bind { companyResult } yields(/* Merge them */) }
  14. Handling exceptions with Monads // userWithCompany is an Either<ExceptionCase, User>

    when(userWithCompany) { is Either.Left -> // Error case is Either.Right -> // Success case }
  15. Monads vs Exceptions Pros: • Safer code • Less tests

    • Less unexpected behaviours Cons: • Complex code • Advanced types + inference = higher compile times
  16. Handling exceptions with Monads val userResult: Either<ExceptionCase, User> = …

    val companyResult: Either<ExceptionCase, Company> = … val userWithCompany = EitherMonad<User>().binding { val user = bind { userResult } val company = bind { companyResult } yields(/* Merge them */) }
  17. Handling exceptions with Monads val userResult: Future<Either<ExceptionCase, User>> = …

    val companyResult: Future<Either<ExceptionCase, Company>> = … val userWithCompany = FutureMonad<User>().binding { val user = bind { userResult } val company = bind { companyResult } yields(/* Merge them */) }
  18. Handling exceptions with Monads val userResult: Future<User> = … val

    companyResult: Future<Company> = … val userWithCompany = FutureMonad<User>().binding { val user = bind { userResult } val company = bind { companyResult } yields(/* Merge them */) }
  19. Handling exceptions with Monads val userResult: Future<User> = … val

    companyResult: Future<Company> = … val userWithCompany = FutureMonad<User>().binding { val user = bind { userResult } // Runs in parallel* val company = bind { companyResult } // Runs in parallel* yields(/* Merge them */) } *Potentially
  20. Handling exceptions with Monads val userResult: Future<User> = … val

    companyResult: Future<Company> = … val userWithCompany = FutureMonad<User>().binding { val user = bind { userResult } val company = bind { companyResult } yields(/* Merge them */) } // WIP :)