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
580
"Fun" as in "funeral": full-stack development using Kotlin JS
paranoidmonoid
0
110
Featured
See All Featured
The Pragmatic Product Professional
lauravandoore
36
6.8k
Reflections from 52 weeks, 52 projects
jeffersonlam
351
21k
BBQ
matthewcrist
89
9.8k
Documentation Writing (for coders)
carmenintech
73
5k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
183
54k
We Have a Design System, Now What?
morganepeng
53
7.7k
Optimizing for Happiness
mojombo
379
70k
Intergalactic Javascript Robots from Outer Space
tanoku
272
27k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
358
30k
Designing for humans not robots
tammielis
253
25k
Automating Front-end Workflow
addyosmani
1370
200k
Producing Creativity
orderedlist
PRO
347
40k
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