Slide 1

Slide 1 text

Slide 2

Slide 2 text

Hi , I am Jorge Castillo, Tech Lead @47deg @jorgecastillopr 

Slide 3

Slide 3 text

Is Kotlin a functional language? 

Slide 4

Slide 4 text

Some valid features ✅ high order functions (functions as values) . val for immutability (properties). Algebraic data types. Sum & Product types (sealed class + data class). Enhances determinism (expressions & exhaustive evaluation). 

Slide 5

Slide 5 text

Is it enough? Nope . It still lacks some important features: type classes, higher kinded types... Something on top of was needed! 

Slide 6

Slide 6 text

Bringing ΛRROW to life 

Slide 7

Slide 7 text

Started as a learning exercise in the Spanish Android Slack community. 

Slide 8

Slide 8 text

Enables Pure Functional Programming over Kotlin. 

Slide 9

Slide 9 text

It's highly modular 

Slide 10

Slide 10 text

How can I use it everyday? 

Slide 11

Slide 11 text

Effectful programs & determinism 

Slide 12

Slide 12 text

Majority of programs contain uncontrolled "effects" . (Query data bases, perform network requests, print to console, render UI...) They escape program's control (can fail, be slow, mutate program's state, race conditions...) 

Slide 13

Slide 13 text

Problem? Unexpected results whenever an effect runs. Non deterministic programs . Frequently called side effects. 

Slide 14

Slide 14 text

Solution? We want program's logic to avoid side effects at all cost, so it can stay deterministic. But, can we avoid them at all? 

Slide 15

Slide 15 text

Solution ✅ Push side effects to the "edge of the world" (program's entry point). Android Application or Activity Rest API controllers other programs main() 

Slide 16

Slide 16 text

How? Depend on abstractions. (Same than OOP! ) Provide implementation details when running it. Effects are implementation details. 

Slide 17

Slide 17 text

Let's step back Our program is composed by functions. A function without side effects is called "pure" ✨. 

Slide 18

Slide 18 text

Pure functions 

Slide 19

Slide 19 text

What is it? A function that is deterministic. Given the same inputs produces the same output without observable world changing effects. 

Slide 20

Slide 20 text

Some small exercises ✏ 

Slide 21

Slide 21 text

Is this pure or impure? Target platform: JVM Running on kotlin v. 1.3.31 fun printHelloWorld() Unit = println("Hello World!") val result = printHelloWorld() 

Slide 22

Slide 22 text

How to make it pure? Defer execution (return a function) Target platform: JVM Running on kotlin v. 1.3.31 fun printHelloWorld() = { println("Hello World!") } val computation = printHelloWorld() 

Slide 23

Slide 23 text

How to make it pure? Alternative: Wrap it into the functional type IO. Defers execution. Fits well in Functional codebases. 

Slide 24

Slide 24 text

Is this pure or impure? Target platform: JVM Running on kotlin v. 1.3.31 fun printHelloWorld() IO = IO { println("Hello World!") } val result = printHelloWorld() 

Slide 25

Slide 25 text

Pure! The thunk is still not run, the computation stays pure until you explicitly run it. 

Slide 26

Slide 26 text

Is this pure or impure? Target platform: JVM Running on kotlin v. 1.3.31 suspend fun printHelloWorld() Unit = println("Hello World!") val result = printHelloWorld() 

Slide 27

Slide 27 text

Why? Suspended functions cannot run outside of an already suspended context. It's unsafe to call them in "the environment" . Kotlin compiler disallows you to run side effects in unsafe places. 

Slide 28

Slide 28 text

The suspended future 

Slide 29

Slide 29 text

@RestrictSuspension suspend fun printOuterHelloWorld() Unit = println(helloWorld()) suspend fun Restricted.printInnerHelloWorld() Unit = println(helloWorld()) @RestrictsSuspension class Restricted { suspend fun y() Unit = printOuterHelloWorld() fails to c suspend fun x() Unit = printInnerHelloWorld() works! } 

Slide 30

Slide 30 text

suspend fun + ΛRROW 

Slide 31

Slide 31 text

ΛRROW Fx Pure functional effects on top of ΛRROW and Kotlin Coroutines System. Leverages direct syntax to write pure functional programs. 

Slide 32

Slide 32 text

Fx DSL 4 primitives to write any possible program. fx {}, effect{}, bind(), unsafe {}. 

Slide 33

Slide 33 text

fx {} Represents a deferred program that can contain effects. Target platform: JVM Running on kotlin v. 1.3.31 suspend fun printHello() Unit = println("Hello world") fun program() IO = fx { printHello() } 

Slide 34

Slide 34 text

You can't plainly run effects in the program! 

Slide 35

Slide 35 text

effect {} Accepts an effect in the program. Wraps the side effects. Target platform: JVM Running on kotlin v. 1.3.31 suspend fun printHello() Unit = println("Hello world") fun program() = fx { effect { printHello() } } 

Slide 36

Slide 36 text

! (or .bind()) Resolves the effect. Equivalent to flatMap(). Target platform: JVM Running on kotlin v. 1.3.31 suspend fun printHello() Unit = println("Hello World") fun program() IO = fx { !effect { printHello() } } fun main() { println(program()) } 

Slide 37

Slide 37 text

bind() removes nesting - service1().flatMap { result1 - service2(result1).flatMap { result2 - service3(result2).map { result3 - Result(result3) - } - } - } + val result1 = !service1() + val result2 = !service2(result1) + val result3 = !service3(result2) + Result(result3) 

Slide 38

Slide 38 text

unsafe {} Perform effects at the edge of the world. Target platform: JVM Running on kotlin v. 1.3.31 fun program() IO = fx { !effect { println("Hello World") } } fun main() { edge of the world unsafe { runBlocking { program() } } } 

Slide 39

Slide 39 text

Polymorphism Make your program parametric to any F. Target platform: JVM Running on kotlin v. 1.3.31 fun Fx.program() Kind = fx { !effect { println("HelloWorld") } } fun main() { val fx = IO.fx() IO as F unsafe { runBlocking { fx.program() } } } 

Slide 40

Slide 40 text

Asynchronous Fibers (Lightweight async processes) 

Slide 41

Slide 41 text

Asynchronous fibers: Easy to spawn and manage Target platform: JVM Running on kotlin v. 1.3.31 fx { val op = effect { Thread.currentThread().name } val fiber = !NonBlocking.startFiber(op) val threadName: String = !fiber.join() !effect { println(threadName) } } 

Slide 42

Slide 42 text

Asynchronous Fibers Recovering from async errors 

Slide 43

Slide 43 text

Asynchronous fibers: Recovering from async errors Target platform: JVM Running on kotlin v. 1.3.31 fx { val op = effect { throw RuntimeException("BOOM!") } val fiber = !NonBlocking.startFiber(op) val recovery = { error: Throwable effect { println("recovering from async exception" } !fiber.join().handleErrorWith(recovery) } 

Slide 44

Slide 44 text

Concurrency: Races Target platform: JVM Running on kotlin v. 1.3.31 fx { val op1 = effect { Thread.currentThread().name } val op2 = effect { Thread.currentThread().name } val op3 = effect { Thread.currentThread().name } val result = !NonBlocking.raceN(op1, op2, op3) !effect { println(result) } } 

Slide 45

Slide 45 text

Concurrency: concurrent non blocking map 

Slide 46

Slide 46 text

Concurrency: Direct style concurrent non blocking map Target platform: JVM Running on kotlin v. 1.3.31 fx { val (a, b, c) = !NonBlocking.parMapN( effect { Thread.currentThread().name }, effect { Thread.currentThread().name }, effect { Thread.currentThread().name }, Tuple3 ) !effect { println(listOf(a, b, c)) } } 

Slide 47

Slide 47 text

Concurrency: Error handling 

Slide 48

Slide 48 text

Concurrency: Error handling Target platform: JVM Running on kotlin v. 1.3.31 fx { val res = !NonBlocking.parMapN( effect { Thread.currentThread().name }, effect { throw RuntimeException("BOOM!") }, effect { Thread.currentThread().name }, Tuple3 ).handleErrorWith { error: Throwable effect { println("One of the ops failed!") } } !effect { println(res) } } 

Slide 49

Slide 49 text

Switching execution contexts Target platform: JVM Running on kotlin v. 1.3.31 val program = fx { continueOn(NonBlocking) val t1 = !effect { Thread.currentThread().name } continueOn(BlockingIO) val t2 = !effect { Thread.currentThread().name } continueOn(UI) val t3 = !effect { Thread.currentThread().name } !effect { println("$t1 $t2 $t3") } } 

Slide 50

Slide 50 text

Bracket: Safe resource acquisition 

Slide 51

Slide 51 text

Bracket: Canceled the usage 

Slide 52

Slide 52 text

Bracket: Error while using it 

Slide 53

Slide 53 text

Target platform: JVM Running on kotlin v. 1.3.31 val program = fx { val acquire = effect { File("data.json").open() } val use = { file: File effect { println(file.toString() val release = { file: File, exitCase: ExitCase effect { when (exitCase) { is ExitCase.Completed println("complete is ExitCase.Canceled println("canceled" is ExitCase.Error println("error") } file.close() println("File closed") } } !acquire.bracketCase(release, use) } 

Slide 54

Slide 54 text

Built in Cancellation Target platform: JVM Running on kotlin v. 1.3.31 fun canceler() = fx { val (_, cancel) = !NonBlocking.startFiber(infiniteLoop()) !effect { delay(100) } !effect { println("main: I'm tired of waiting!") } !cancel !effect { println("main: Now I can quit.") } } 

Slide 55

Slide 55 text

Abstracts over function arity Target platform: JVM Running on kotlin v. 1.3.31 val program = fx { val op1 = effect { "first" } val op2 = effect { 2 } val race = !NonBlocking.raceN(op1, op2) val winner = race.fold({ "first one won" }, { "second one !effect { println(winner) } } 

Slide 56

Slide 56 text

Fx for all Monads Fx over Option Target platform: JVM Running on kotlin v. 1.3.31 fx { val one = !Option(1) val two = !Option(one + one) two } 

Slide 57

Slide 57 text

Alternative ! styles (_) destructuring syntax Target platform: JVM Running on kotlin v. 1.3.31 fx { val (one) = Option(1) val (two) = Option(one + one) two } 

Slide 58

Slide 58 text

Alternative ! styles explicit bind() Target platform: JVM Running on kotlin v. 1.3.31 fx { val one = Option(1).bind() val two = Option(one + one).bind() two } 

Slide 59

Slide 59 text

Ecosystem and roadmap 

Slide 60

Slide 60 text

KEEP-87 We want to make Typed FP in Kotlin even easier 

Slide 61

Slide 61 text

KEEP-87 Big expectations from the Kotlin community 

Slide 62

Slide 62 text

Where is the code ? and -> @tomasruizlopez @jorgecastillopr KEEP-87 

Slide 63

Slide 63 text

KEEP-87 Proposes Compile time DI. Families (scopes) of functions validated and injected at compile time. 

Slide 64

Slide 64 text

KEEP-87 KEEP is already submitted ✅ . We're gathering feedback and will iterate further after JetBrains review. 

Slide 65

Slide 65 text

Upcoming libraries Helios: Hyper fast serialization library (optics based! awesome syntax) ⚡ . Kollect: Efficient data loading from heterogeneous sources of data . Both are FP oriented, fit well in any programs using Kotlin + FP. More to come!: Streams, Android... 

Slide 66

Slide 66 text

Helios 0.1.0 

Slide 67

Slide 67 text

Where's Arrow? Already available in Maven Central and JCenter. Aiming for a first stable release around the end of 2019 . 

Slide 68

Slide 68 text

We want you in 

Slide 69

Slide 69 text

Join us! Github Slack Gitter We are beginner friendly and provide 1:1 mentoring for both users & new contributors! +110 Contributors and growing! https://github.com/arrow-kt https://kotlinlang.slack.com/messages/C5UPMM0A0 https://gitter.im/arrow-kt/Lobby 

Slide 70

Slide 70 text