Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Hands-on Arrow
Search
Karin-Aleksandra Monoid
February 12, 2021
1
160
Hands-on Arrow
Karin-Aleksandra Monoid
February 12, 2021
Tweet
Share
More Decks by Karin-Aleksandra Monoid
See All by Karin-Aleksandra Monoid
Extending kotlinx.serialization functionality with Arrow Meta (Joker 2021/KotlinDevDay 2022)
paranoidmonoid
0
110
Treasure.map(): Functional programming in JVM-based languages
paranoidmonoid
0
320
Extending kotlinx.serialization functionality with Arrow Meta
paranoidmonoid
0
110
Functional Kotlin with Arrow (jLove 2021)
paranoidmonoid
1
210
Make Tech Slides Work
paranoidmonoid
0
570
"Fun" as in "funeral": full-stack development using Kotlin JS
paranoidmonoid
0
110
Featured
See All Featured
Gamification - CAS2011
davidbonilla
81
5.3k
Optimising Largest Contentful Paint
csswizardry
37
3.3k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
17
950
Fireside Chat
paigeccino
37
3.5k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
Writing Fast Ruby
sferik
628
62k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.5k
Optimizing for Happiness
mojombo
379
70k
A Tale of Four Properties
chriscoyier
160
23k
Raft: Consensus for Rubyists
vanstee
140
7k
BBQ
matthewcrist
89
9.7k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.8k
Transcript
Karin-Aleksandra Monoid GDG Nuremberg, 2021 Hands-on Arrow (How we filled
Kotlin standard library gaps without converting code to Scala)
Agenda • What is Arrow? • NonEmptyList • Either •
Monad Comprehensions
What is Arrow?
What is Arrow? 4 4 Core FX Optics Meta
What is Arrow? 5 5 Core FX Optics Meta
NonEmptyList
Non-empty list Is JSON {“payments”: []} ok? 7 7 Payments
List of items (Phone, Reference, Amount) Phone ... String(100) Required Reference ... String(100) Required Amount ... Decimal Required
Non-empty list NonEmptyList.of() // does not compile NonEmptyList.of(1, 2, 3,
4, 5) // NonEmptyList<Int> 8 8
Non-empty list NonEmptyList.of() // does not compile NonEmptyList.of(1, 2, 3,
4, 5) // NonEmptyList<Int> 9 9
Either
Java Exceptions if (somethingWrong) throw new SomeException(...) 11 11
Java Exceptions - “Handling” in signature void testFun() throws SomeException
12 12
Java Exceptions - Handling with try try { testFun() }
catch (SomeException e) { ... } 13 13
Java Exceptions IntStream.range(0, 10) .forEach(i -> testFun()) 14 14
Java Exceptions IntStream.range(0, 10) .forEach(i -> testFun()) 15 15
Java Exceptions IntStream.range(0, 10) .forEach(hideException(i -> testFun())); 16 16
Java Exceptions unhideSomeException(() -> IntStream.range(0, 10) .forEach( hideException(i -> testFun()
))); 17 17
Kotlin Exceptions • No more checked exceptions (like Scala, Groovy
and everyone else) 18 18
Kotlin Exceptions (1 until 10).forEach { testFun() } 19 19
Null fun String.toIntOrNull(): Int? • Not expressive • ????? •
null-checks 20 20
Result Type inline class Result<out T> : Serializable 21 21
Result Type 22 22 fun deserialize(): Something { return try
{ doSomething() } catch (_: Exception) { try { doSomethingElse() } catch(_: Exception) { doSomethingElseAgain() }}... fun deserialize(): Something { return runCatching { doSomething() }.recoverCatching { doSomethingElse() }.getOrElse { doSomethingElseAgain() } }
Sealed Type sealed class Result class Success : Result() class
FullMoonFailure : Result() class ElonMuskTweetedFailure : Result() 23 23
Either sealed class Either<out A, out B> 24 24
Validated sealed class Validated<out A, out B> 25 25
Validated vs Either • Either stops at first fail, validated
collects all: User(phone, name, age) User(“test”, XÆA-12 Musk, -10) • Either: invalid phone • Validated: invalid phone, name*, age 26 26 * https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/
Monad comprehensions
Require requireNotNull(request.userId) requireNotNull(request.transaction.id) 28 28
Require public inline fun <T : Any> requireNotNull (value: T?):
T { contract { returns() implies (value != null) } return requireNotNull(value) { "Required value was null." } } 29 29
if-else-if-else-if-else if(request.userId == null) return buildExceptionResponse(...) if(request.transaction.id == null) return
buildExceptionResponse(...) ... 30 30
Arrow Monads 31 31 https://chrisdone.com/posts/monads-are-burritos/
Arrow Monads 32 32 inline fun <T, R> Iterable<T>.flatMap( transform:
(T) -> Iterable<R> ): List<R>
Chaining - flatMap val response = checkForNull(...) .flatMap { userId
-> checkForNull(...).flatMap { paymentId -> checkForNull(...).flatMap { items -> checkForNull(...).flatMap { status -> checkForNull(...).map { ( … )}}}}}}}}} 33 33
Chaining - monad comprehensions val response = Either.fx { val
userId = checkForNull(request.userId).bind() val paymentId = checkForNull(request.transaction.id).bind() val items = checkForNull(request.transaction.items).bind() val status = client.checkPaymentStatus(userId,...) // ... } return response.getOrHandle { it } private fun <T : Any> checkForNull(param: T?, paramName: String): Either<ErrorResponse, T> 34 34
None