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
170
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Hands-on Arrow
Karin-Aleksandra Monoid
February 12, 2021
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
130
Treasure.map(): Functional programming in JVM-based languages
paranoidmonoid
0
340
Extending kotlinx.serialization functionality with Arrow Meta
paranoidmonoid
0
130
Functional Kotlin with Arrow (jLove 2021)
paranoidmonoid
1
240
Make Tech Slides Work
paranoidmonoid
0
620
"Fun" as in "funeral": full-stack development using Kotlin JS
paranoidmonoid
0
130
Featured
See All Featured
Building Adaptive Systems
keathley
44
3.2k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Building an army of robots
kneath
306
46k
Practical Orchestrator
shlominoach
191
12k
BBQ
matthewcrist
89
10k
How STYLIGHT went responsive
nonsquared
100
6.2k
KATA
mclloyd
PRO
35
15k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
440
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
200
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
460
Abbi's Birthday
coloredviolet
3
9k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
890
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