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

Treasure.map(): Functional programming in JVM-based languages

Treasure.map(): Functional programming in JVM-based languages

Karin-Aleksandra Monoid

June 08, 2022
Tweet

More Decks by Karin-Aleksandra Monoid

Other Decks in Programming

Transcript

  1. 2 • Senior Software Engineer at CircleCI • Background in

    Kotlin & Scala (both front and backend) • Living in Potsdam with two cats • GDE in Kotlin About
  2. 4 “Why can we tell people about internals of JVM

    and no one bats an eye but should I only add a word “monad” and everyone is too scared because it’s so difficult?” – Conclusions on the speaker dinner/Joker 2021 Motivation
  3. 9 Pure functions • Same input = same output •

    No “side-effects” • Not altering any global state
  4. 10 Immutability • Java: records, final, vavr • Kotlin: val,

    read-only collection interfaces, Arrow, kotlinx.collections.immutable • Scala: vals, scala.collection.* and scala.collection.immutable.* • Clojure: everything but def • Groovy: @Immutable meta-annotation, asImmutable()
  5. 11 True immutability vs reference immutability? Java: final List<Integer> list

    = Arrays.asList(1, 2, 3); We can’t reassign it like list = Arrays.asList(1, 2, 6); But can alter the list itself e.g. with set(0, 10) We can wrap with unmodifiableList or use List.of to begin with, but we don’t know by type whether provided list is mutable (ArrayList), semi-mutable (Arrays.asList) or unmodifiable. Also deep structures are not covered.
  6. 13 Collection immutability: Scala scala.collection.* - you cannot modify but

    somebody else might be able to. scala.collection.immutable.* - nobody can modify collection itself scala.collection.mutable.* - you can modify this
  7. 14 Collection immutability: Kotlin Collection, List, etc - you cannot

    modify but somebody else might be able to. MutableCollection, MutableList, etc - you can modify this ImmutableList (from kotlinx.collections.immutable) - nobody can modify collection/list
  8. 16 Map (🐸, 🐸, 🐸).map(🐸 -> 🦄) => (🦄, 🦄,

    🦄) Java items.stream().map(frog -> unicorn).toList() Groovy items.collect(frog -> unicorn) Kotlin items.map { frog -> unicorn } Scala items.map(frog => unicorn) Clojure (map (constantly unicorn) items)
  9. 17 Filter (🐸, 🐸, 🦄, 🦄, 🐸, 🦄).filter(🐸?) => (🐸,

    🐸, 🐸) Java items.stream().filter(Animal::isFrog).toList() Groovy items.findAll { it.isFrog() } Kotlin items.filter { it.isFrog() } Scala items.filter(isFrog(_)) Clojure (filter is-frog? items)
  10. 18 Fold (👩, 👩, 👧, 👦).fold(+) => 󰔮 Java items.stream().collect(collector)

    Groovy items.inject(acc, …) Kotlin items.fold(acc) {...} Scala tems.fold(acc)(...) Clojure (r/fold function acc items)
  11. 19 FlatMap (🟧, 🟨, 🟩, 🟦).flatMap(⬜ -> (🤍, ⚪)) =>

    (🧡, 🟠, 💛, 🟡, 💚, 🟢, 💙, 🔵) Java items.stream.flatMap(...).toList() Groovy items.collectMany(...) Kotlin items.flatMap {...} Scala items.flatMap(...) Clojure (mapcat transform items)
  12. 21 A monad A monad is just a monoid in

    a category of the endofunctors
  13. 22 Monads Do you know monads? Do you use a

    `List`? That’s a monad!
  14. 23 Monads in the simple terms A type: • An

    instance of which can be created • Which has flatMap() function
  15. 24 Monad comprehensions combined = for { a <- listA

    b <- listB } yield a * b Which is equal to combined = listA.flatMap(a => listB.flatMap(b => a * b))
  16. 25 Monad comprehensions combined = for { a <- optionA

    b <- optionB } yield a * b Which is equal to combined = optionA.flatMap(a => optionB.flatMap(b => a * b))
  17. 29 Java Exceptions - Handling with try try { testFun()

    } catch (SomeException e) { ... }
  18. 35 Demo K: (0 until 10).forEach { testFun() } S:

    (0 until 10).foreach { testFun() } C: (run test-fun (range 10)) G: (1..<3).each { testFun() }
  19. 39 How to handle problems: Kotlin, sealed types sealed class

    Result class SuccessfullyInvested : Result() class LostMoney : Result()
  20. 40 How to handle problems: Scala, Option Something or none

    def toIntOption: Option[Int] Some(5) or None
  21. 41 How to handle problems: Scala, Either val result: Either[DbError,

    User] = db.findUser(id) Left(UserNotFound) or Right(User(123))
  22. 42 How to handle problems: Scala, Either Either is also

    a monad val userSummary = for { user <- db.findUser(id) balance <- db.findUserBalance(user.bankId) } yield UserSummary(user, balance)
  23. 46 Frameworks and libraries Java, Groovy: vavr Kotlin: Arrow Scala:

    Cats, zio Clojure: just continue using REPL
  24. 47 • You are using elements of FP already •

    Consider support of libraries • Consider team knowledge • Immutability may be slow-ish Conclusions