SlideShare a Scribd company logo
1 of 72
training@instil.co
June 2018
© Instil Software 2018
Coding in Kotlin with Arrow
NIDC 2018
https://gitlab.com/instil-training/nidc-arrow-2018
About Me
Experienced trainer
• 20 years in the trenches
• Over 1000 deliveries
The day job
• Head of Learning at Instil
• Coaching, mentoring etc…
The night job(s)
• Husband and father
• Krav Maga Instructor
A quick Kotlin refresher
• Kotlin compared to Java
Introducing Arrow
• What is it and why does it matter?
Arrow Pt1: Data Types
• Option, Try, Either and Validated
Arrow Pt2: Enhanced FP
• Partial Invocation, Currying and Composition
Arrow Pt3: Esoteric Stuff
• Lenses, IO etc…
Agenda For This Talk
• A Quick Language Overview
Kotlin Refresher
Enter some numbers or three 'X' to finish
10
20
30
40
50
XXX
Total of numbers is: 150
Enter some numbers or three 'X' to finish
wibble
Ignoring wibble
12
13
14
XXX
Total of numbers is: 39
Enter some numbers or three 'X' to finish
XXX
Total of numbers is: 0
public class Program {
public static void main(String[] args) {
@SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
List<Integer> numbers = new ArrayList<>();
System.out.println("Enter some numbers or three 'X' to finish");
Pattern endOfInput = Pattern.compile("X{3}");
while(scanner.hasNextLine()) {
if (scanner.hasNext(endOfInput)) {
break;
} else if (scanner.hasNextInt()) {
numbers.add(scanner.nextInt());
} else {
String mysteryText = scanner.nextLine();
System.out.printf("Ignoring %sn", mysteryText);
}
}
int total = numbers.stream().reduce((a,b) -> a + b).orElse(0);
System.out.printf("Total of numbers is: %sn",total);
}
}
A Sample Java Program
fun main(args: Array<String>) {
val numbers = mutableListOf<Int>()
val scanner = Scanner(System.`in`)
val endOfInput = Regex("X{3}")
println("Enter some numbers or three 'X' to finish")
while (scanner.hasNextLine()) {
if (scanner.hasNext(endOfInput.toPattern())) {
break
} else if (scanner.hasNextInt()) {
numbers += scanner.nextInt()
} else {
val mysteryText = scanner.nextLine()
println("Ignoring $mysteryText")
}
}
//Would be better to use ‘numbers.sum()’
val total = numbers.fold(0, Int::plus)
println("Total of numbers is: $total")
}
The Sample Re-Written in Kotlin
Points to note:
 No redundant class
 No semi-colons
 Type inference
 Both ‘val’ and ‘var’
 Helper functions
 String interpolation
 Simplified collections
 Interop with Java types
 Simpler use of FP
• What is it?
• Why does it matter?
Introducing Arrow
Languages Today Are Converging
The Great Scala vs. Kotlin Debate
I am an Enterprise
Coder. Like my father
before me
You fool. If only you
knew the power of
Monads!
How Much Functional Programming is ‘Just Right’?
One Possible Solution…
Arrow is a functional programming library for Kotlin coders
• Launched in Jan when the two leading libraries joined forces
• To prevent the ‘Scalaz vs. Cats’ debate that exists in Scala
It is not a formal part of the Kotlin environment
• But is generating a lot of interest in the Kotlin community
• It has resulted in proposals for changes to the language
Learning Arrow can be a bit frustrating as:
• The documentation is incomplete and patchy
• Changes are still occurring between releases
• Sample code is hard to find….
I’m still learning what its all about!
• This is very much a report on my progress so far…
Introducing Arrow
Part One: Data Types
Lets Do The Same Thing Many Times 
Option
fun readPropertyA(name: String): Option<String> {
val result = System.getProperty(name)
return if(result != null) Some(result) else None
}
fun readPropertyB(name: String) =
Option.fromNullable(System.getProperty(name))
Reading Property Values Safely Via Option
<<abstract>>
Option
Some None
Empty SetSet of One
fun print1(input: Option<String>): Unit {
when(input) {
is None -> println("Nothing was found")
is Some -> println("'${input.t}' was found")
}
}
fun print2(input: Option<String>): Unit {
println("${input.getOrElse { "Nothing" }} was found")
}
Reading Property Values Safely Via Option
fun print3(input: Option<String>): Unit {
val result = input.fold({ "Nothing" }, { it })
println("$result was found")
}
fun print4(input1: Option<String>, input2: Option<String>): Unit {
val result = input1.flatMap { first ->
input2.map { second ->
"$first and $second"
}
}
println("Results are ${result.getOrElse { "Nothing" }}")
}
Reading Property Values Safely Via Option
fun main(args: Array<String>) {
print1(readPropertyA("java.version"))
print1(readPropertyA("wibble"))
printLine()
print2(readPropertyB("java.version"))
print2(readPropertyB("wibble"))
printLine()
print3(readPropertyA("java.version"))
print3(readPropertyA("wibble"))
printLine()
print4(
readPropertyA("java.version"),
readPropertyB("java.version")
)
printLine()
print4(
readPropertyA("java.version"),
readPropertyB("wibble")
)
printLine()
print4(readPropertyA("wibble"), readPropertyB("wibble"))
printLine()
print4(readPropertyA("wibble"), readPropertyB("wibble"))
}
Reading Property Values Safely Via Option
Reading Property Values Safely Via Option
'1.8.0_121' was found
Nothing was found
---------------
1.8.0_121 was found
Nothing was found
---------------
1.8.0_121 was found
Nothing was found
---------------
Results are 1.8.0_121 and 1.8.0_121
---------------
Results are Nothing
---------------
Results are Nothing
---------------
Results are Nothing
class Postcode(val input: String?) {
fun value() = Option.fromNullable(input)
}
class Address(val street: String, val postcode: Postcode?) {
fun location() = Option.fromNullable(postcode)
}
class Person(val name: String, val address: Address?) {
fun residence() = Option.fromNullable(address)
}
Using Option as a Monad
fun printPostcode(person: Person) {
val result = Option.monad().binding {
val address = person.residence().bind()
val location = address.location().bind()
location.value().bind()
}.fix()
println(result.fold( { "No postcode available" },
{ "Postcode of $it" }))
}
Using Option as a Monad
fun main(args: Array<String>) {
printPostcode(Person("Dave",
Address("10 Arcatia Road",
Postcode("ABC 123"))))
printPostcode(Person("Dave",
Address("10 Arcatia Road", null)))
printPostcode(Person("Dave", null))
}
Using Option as a Monad
Postcode of ABC 123
No postcode available
No postcode available
Try
fun firstLine(path: String): Try<String> {
fun readFirstLine(path: String): String {
val reader = BufferedReader(FileReader(path))
return reader.use { it.readLine() }
}
return Try { readFirstLine(path) }
}
Reading the First Line from a File via Try
<<abstract>>
Try
Success Failure
Holds ErrorHolds Result
fun print1(input: Try<String>): Unit {
when(input) {
is Success -> println("Read '${input.value}'")
is Failure -> println("Threw '${input.exception.message}'")
}
}
fun print2(input: Try<String>): Unit {
val result = input.fold( { "Threw '${it.message}'" },
{ "Read '$it'" })
println(result)
}
fun print3(input: Try<String>): Unit {
input.map { println("Read '$it'") }
input.recover { println("Threw '${it.message}'") }
}
Reading the First Line from a File via Try
Lets Have Some Fun 
fun print4(input: String) {
fun fullPath(str: String) = "data/$str"
val finalResult = firstLine(fullPath(input)).flatMap { one ->
firstLine(fullPath(one)).flatMap { two ->
firstLine(fullPath(two)).flatMap { three ->
firstLine(fullPath(three)).flatMap { four ->
firstLine(fullPath(four)).map { result ->
result
}
}
}
}
}
val message = finalResult.fold({ it.message }, { it })
println("Path navigation produced '$message'")
}
Traversing Across Files
fun main(args: Array<String>) {
print1(firstLine("data/input4.txt"))
print1(firstLine("foobar.txt"))
printLine()
print2(firstLine("data/input4.txt"))
print2(firstLine("foobar.txt"))
printLine()
print3(firstLine("data/input4.txt"))
print3(firstLine("foobar.txt"))
printLine()
print4("input.txt")
print4("foobar.txt")
}
Reading the First Line from a File via Try
Traversing Across Files
Read 'Fortune favors the prepared mind'
Threw 'foobar.txt (No such file or directory)'
---------------
Read 'Fortune favors the prepared mind'
Threw 'foobar.txt (No such file or directory)'
---------------
Read 'Fortune favors the prepared mind'
Threw 'foobar.txt (No such file or directory)'
---------------
Path navigation produced 'Fortune favors the prepared mind'
Path navigation produced 'data/foobar.txt (No such file or directory)'
fun readFromFiles(input: String): String? {
val result = Try.monad().binding {
val one = firstLine(fullPath(input)).bind()
val two = firstLine(fullPath(one)).bind()
val three = firstLine(fullPath(two)).bind()
val four = firstLine(fullPath(three)).bind()
firstLine(fullPath(four)).bind()
}.fix()
return result.fold({ it.message }, { it })
}
Traversing Across Files
fun main(args: Array<String>) {
println("Path navigation produced '${readFromFiles("input.txt")}'")
println("Path navigation produced '${readFromFiles("foobar")}'")
}
Traversing Across Files
Path navigation produced 'Fortune favors the prepared mind'
Path navigation produced 'data/foobar (No such file or directory)'
Either
fun genNumber() : Either<Int, Int> {
val number = (random() * 100).toInt()
return if(number % 2 == 0) Right(number)
else Left(number)
}
Using the Either Type
<<abstract>>
Either
Left Right
Happy PathAlternative
fun main(args: Array<String>) {
val results = (1 .. 10).map {
genNumber().flatMap { first ->
genNumber().map { second ->
Pair(first, second)
}
}
}
results.forEach { result ->
val msg = result.fold(
{ "Odd number $it" },
{ "Even numbers ${it.first} and ${it.second}" }
)
println(msg)
}
}
Using the Either Type Even numbers 50 and 40
Odd number 77
Even numbers 52 and 32
Odd number 25
Odd number 89
Even numbers 80 and 54
Odd number 65
Odd number 1
Odd number 1
Odd number 33
fun checkNum(number:Int) : Either<Int, Int> {
return if(number % 2 == 0) Right(number) else Left(number)
}
class EitherTest : ShouldSpec() {
init {
should("be able to detect Right") {
checkNum(4).shouldBeRight(4)
}
should("be able to detect Left") {
checkNum(5).shouldBeLeft(5)
}
}
}
All Arrow Types are Supported in KotlinTest
Validated
Our Sample Problem
Whats your ID?
ab12
How old are you?
19
Where do you work?
HR
Error: Bad ID
Whats your ID?
AB12
How old are you?
19
Where do you work?
IT
Result: AB12 of age 19 working in IT
Whats your ID?
ab12
How old are you?
14
Where do you work?
Mars
Error: Bad Dept Bad ID Bad Age
class Employee(val id: String, val age: Int, val dept: String) {
override fun toString() = "$id of age $age working in $dept"
}
fun askQuestion(question: String): String {
println(question)
return readLine() ?: ""
}
Reading and Validating Information
<<abstract>>
Validated
Invalid Valid
ResultMessage
fun checkID(): Validated<String, String> {
val regex = Regex("[A-Z]{2}[0-9]{2}")
val response = askQuestion("Whats your ID?")
return if(regex.matches(response)) Valid(response)
else Invalid("Bad ID")
}
fun checkAge(): Validated<String, Int> {
val response = askQuestion("How old are you?").toInt()
return if(response > 16) Valid(response) else Invalid("Bad Age")
}
fun checkDept(): Validated<String, String> {
val depts = listOf("HR", "Sales", "IT")
val response = askQuestion("Where do you work?")
return if(depts.contains(response)) Valid(response)
else Invalid("Bad Dept")
}
Reading and Validating Information
fun main(args: Array<String>) {
val sg = object : Semigroup<String> {
override fun String.combine(b: String) = "$this $b"
}
val id = checkID()
val age = checkAge()
val dept = checkDept()
val result = Validated.applicative(sg)
.map(id, age, dept, {
(a,b,c) -> Employee(a,b,c)
})
.fix()
println(result.fold({ "Error: $it" }, {"Result: $it"} ))
}
Reading and Validating Information
Using Types In Combination
Our example of Validated contained a bug…
• We assumed the value given for ‘age’ would be an integer
Composing Types
Whats your ID?
AB12
How old are you?
abc
Exception in thread "main" java.lang.NumberFormatException: For input string: "abc"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at arrow.types.validated.ProgramKt.checkAge(Program.kt:22)
at arrow.types.validated.ProgramKt.main(Program.kt:37)
fun checkAge(): Validated<String, Int> {
val response = askQuestion("How old are you?").toInt()
return if(response > 16) Valid(response)
else Invalid("Bad Age")
}
Composing Types
We can solve the problem by composing types together
• Our methods should return a Try<Validated<T,U>>
Composing Types
fun checkID(): Try<Validated<String, String>> {
val regex = Regex("[A-Z]{2}[0-9]{2}")
val response = askQuestion("Whats your ID?")
return Try { if(regex.matches(response)) Valid(response)
else Invalid("Bad ID") }
}
fun checkAge(): Try<Validated<String, Int>> {
val response = Try { askQuestion("How old are you?").toInt() }
return response.map({ num -> if(num > 16) Valid(num)
else Invalid("Bad Age")})
}
Composing Types
fun checkSalary(): Try<Validated<String, Double>> {
val response = Try { askQuestion("What is your salary?")
.toDouble() }
return response.map({ num -> if(num > 15000.0) Valid(num)
else Invalid("Bad Salary") })
}
fun checkDept(): Try<Validated<String, String>> {
val depts = listOf("HR", "Sales", "IT")
val response = askQuestion("Where do you work?")
return Try { if(depts.contains(response)) Valid(response)
else Invalid("Bad Dept") }
}
Composing Types
fun success(emp: Employee)
= println("Created $emp")
fun exception(ex: Throwable)
= println("Exception occurred - ${ex.message}")
fun invalid(msg: String?)
= println("Validation error occurred - $msg")
class Employee(val id: String, val age: Int,
val dept: String, val salary: Double) {
constructor(t: Tuple4<String,Int,String,Double>) :
this(t.a,t.b,t.c,t.d)
override fun toString()
= "$id of age $age working in $dept earning $salary"
}
Composing Types
Composing Types
Try<Validated<T,U>>
Failure
Success<Validated<T,U>>
exception()
Valid<U>
Invalid<T>
success()
invalid()
fun main(args: Array<String>) {
val app = Validated.applicative(object : Semigroup<String> {
override fun String.combine(b: String) = "$this $b"
})
Try.monad().binding {
val id = checkID().bind()
val age = checkAge().bind()
val dept = checkDept().bind()
val salary = checkSalary().bind()
app.map(id, age, dept, salary, ::Employee).fix()
}.fix().fold(
{exception(it)},
{it.fold(::invalid,::success)})
}
Composing Types
Composing Types
Whats your ID?
AB12
How old are you?
abc
Exception occurred - For input string: "abc"
Whats your ID?
AB12
How old are you?
21
Where do you work?
Sales
What is your salary?
abc
Exception occurred - For input string: "abc"
Whats your ID?
foo
How old are you?
21
Where do you work?
Sales
What is your salary?
30000.0
Validation error occurred - Bad ID
Whats your ID?
AB12
How old are you?
21
Where do you work?
foo
What is your salary?
30000.0
Validation error occurred - Bad Dept
Composing Types
Whats your ID?
AB12
How old are you?
21
Where do you work?
Sales
What is your salary?
30000.0
Created AB12 of age 21 working in Sales earning 30000.0
Part Two: Functions
Partial Invocation
fun demo1() {
val addNums = { no1: Int, no2: Int ->
println("Adding $no1 to $no2")
no1 + no2
}
val addSeven = addNums.partially2(7)
val result = addSeven(3)
println(result)
}
Partial Invocation
Adding 3 to 7
10
fun demo2() {
val addNums = { no1: Int, no2: Int ->
println("Adding $no1 to $no2")
no1 + no2
}
val addSeven = addNums.partially2(7)
val addSevenToThree = addSeven.partially1(3)
val result = addSevenToThree()
println(result)
}
Partial Invocation
Adding 3 to 7
10
fun demo3() {
val addNums = { no1: Int, no2: Int ->
println("Adding $no1 to $no2")
no1 + no2
}
val addSeven = addNums.reverse().partially2(7)
val result = addSeven(3)
println(result)
}
Partial Invocation
Adding 7 to 3
10
fun grep(path: String, regex: Regex, action: (String) -> Unit) {
val reader = BufferedReader(FileReader(path))
reader.use {
it.lines()
.filter { regex.matches(it) }
.forEach(action)
}
}
val grepLambda = { a: String, b: Regex, c: (String) -> Unit ->
grep(a, b, c)
}
fun printLine() = println("-------------")
Here’s Something More Useful
val filePath = "data/grepInput.txt"
val regex = "[A-Z]{2}[0-9]{2}".toRegex()
grep(filePath, regex, ::println)
printLine()
grepLambda(filePath, regex, ::println)
printLine()
Here’s Something More Useful
AB12
CD34
EF56
-------------
AB12
CD34
EF56
-------------
val grepAndPrint = grepLambda.partially3(::println)
grepAndPrint(filePath, regex)
printLine()
val sb = StringBuilder()
val grepAndConcat = grepLambda.partially3 {sb.append(it)}
grepAndConcat(filePath, regex)
println(sb.toString())
printLine()
val grepAndPrintRegex = grepAndPrint.partially2(regex)
grepAndPrintRegex(filePath)
Here’s Something More Useful
AB12
CD34
EF56
-------------
AB12CD34EF56
-------------
AB12
CD34
EF56
Currying
val addThree = { a:Int, b: Int, c:Int ->
println("Adding $a, $b and $c")
a + b + c
}
fun printLine() = println("--------------------")
fun main(args: Array<String>) {
println(addThree(10,20,40))
printLine()
val f1 = addThree.curried()
val f2 = f1(10)
val f3 = f2(20)
val result = f3(40)
println(result)
printLine()
println(f1(10)(20)(40))
printLine()
val f4 = addThree.reverse().curried()
println(f4(10)(20)(40))
println()
}
The Basic Syntax of Currying
Adding 10, 20 and 40
70
--------------------
Adding 10, 20 and 40
70
--------------------
Adding 10, 20 and 40
70
--------------------
Adding 40, 20 and 10
70
fun grep(path: String, regex: Regex, action: (String) -> Unit) {
val reader = BufferedReader(FileReader(path))
reader.use {
it.lines()
.filter { regex.matches(it) }
.forEach(action)
}
}
val grepLambda = { a: String, b: Regex, c: (String) -> Unit ->
grep(a,b,c) }
fun printLine() = println("-------------")
A More Useful Example
fun main(args: Array<String>) {
val filePath = "data/grepInput.txt"
val regex1 = "[A-Z]{2}[0-9]{2}".toRegex()
val regex2 = "[a-z]{2}[0-9]{2}".toRegex()
val f1 = grepLambda.curried()
val grepInFile = f1(filePath)
val grepRegex1 = grepInFile(regex1)
val grepRegex2 = grepInFile(regex2)
grepRegex1(::println)
printLine()
grepRegex2(::println)
}
A More Useful Example
AB12
CD34
EF56
-------------
ab12
cd34
ef56
Composition
val source = { name: String -> "data/$name" }
val allLines = { path: String ->
val reader = BufferedReader(FileReader(path))
reader.use {
it.lines().toList()
}
}
val findMatches = { input: List<String> ->
val regex = "[A-Z]{2}[0-9]{2}".toRegex()
input.filter(regex::matches)
}
Composing Functions Together
fun main(args: Array<String>) {
val composed1 = findMatches compose allLines compose source
println(composed1("grepInput.txt"))
val composed2 = source forwardCompose allLines forwardCompose findMatches
println(composed2("grepInput.txt"))
val composed3 = source andThen allLines andThen findMatches
println(composed3("grepInput.txt"))
}
Composing Functions Together
[AB12, CD34, EF56]
[AB12, CD34, EF56]
[AB12, CD34, EF56]
Part 3: Weird Stuff
Lenses
@optics
data class Postcode(val value: String) {
override fun toString() = "$value"
}
@optics
data class Address(val street: String, val postcode: Postcode) {
override fun toString() = "$street ($postcode)"
}
@optics
data class Person(val name: String, val address: Address) {
override fun toString() = "$name living at $address"
}
Copying Immutable Structures With Lenses
fun main(args: Array<String>) {
val oldPerson = Person("Dave",
Address("10 Arcatia Road",
Postcode("BT26 ABC")))
println(oldPerson)
val personAddressPostcode
= personAddress() compose addressPostcode() compose postcodeValue()
val newPerson
= personAddressPostcode.modify(oldPerson, { _ -> "BT37 DEF" })
println(newPerson)
}
Copying Immutable Structures With Lenses
Dave living at 10 Arcatia Road (BT26 ABC)
Dave living at 10 Arcatia Road (BT37 DEF)

More Related Content

What's hot

Introduction to Python - Part Two
Introduction to Python - Part TwoIntroduction to Python - Part Two
Introduction to Python - Part Twoamiable_indian
 
Intro to Functions Python
Intro to Functions PythonIntro to Functions Python
Intro to Functions Pythonprimeteacher32
 
Basic Python Programming: Part 01 and Part 02
Basic Python Programming: Part 01 and Part 02Basic Python Programming: Part 01 and Part 02
Basic Python Programming: Part 01 and Part 02Fariz Darari
 
EuroPython 2016 - Do I Need To Switch To Golang
EuroPython 2016 - Do I Need To Switch To GolangEuroPython 2016 - Do I Need To Switch To Golang
EuroPython 2016 - Do I Need To Switch To GolangMax Tepkeev
 
Chapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYA
Chapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYAChapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYA
Chapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYAMaulik Borsaniya
 
Basics of Python programming (part 2)
Basics of Python programming (part 2)Basics of Python programming (part 2)
Basics of Python programming (part 2)Pedro Rodrigues
 
Kotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime PerformanceKotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime Performanceintelliyole
 
Programming in Python
Programming in Python Programming in Python
Programming in Python Tiji Thomas
 
PPT on Data Science Using Python
PPT on Data Science Using PythonPPT on Data Science Using Python
PPT on Data Science Using PythonNishantKumar1179
 
Python Performance 101
Python Performance 101Python Performance 101
Python Performance 101Ankur Gupta
 
Euro python2011 High Performance Python
Euro python2011 High Performance PythonEuro python2011 High Performance Python
Euro python2011 High Performance PythonIan Ozsvald
 
Odessapy2013 - Graph databases and Python
Odessapy2013 - Graph databases and PythonOdessapy2013 - Graph databases and Python
Odessapy2013 - Graph databases and PythonMax Klymyshyn
 
SQL Server Select Topics
SQL Server Select TopicsSQL Server Select Topics
SQL Server Select TopicsJay Coskey
 
15. Streams Files and Directories
15. Streams Files and Directories 15. Streams Files and Directories
15. Streams Files and Directories Intro C# Book
 

What's hot (20)

Introduction to Python - Part Two
Introduction to Python - Part TwoIntroduction to Python - Part Two
Introduction to Python - Part Two
 
Intro to Functions Python
Intro to Functions PythonIntro to Functions Python
Intro to Functions Python
 
Python Basics
Python BasicsPython Basics
Python Basics
 
Basic Python Programming: Part 01 and Part 02
Basic Python Programming: Part 01 and Part 02Basic Python Programming: Part 01 and Part 02
Basic Python Programming: Part 01 and Part 02
 
EuroPython 2016 - Do I Need To Switch To Golang
EuroPython 2016 - Do I Need To Switch To GolangEuroPython 2016 - Do I Need To Switch To Golang
EuroPython 2016 - Do I Need To Switch To Golang
 
Chapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYA
Chapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYAChapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYA
Chapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYA
 
Introduction to Kotlin
Introduction to KotlinIntroduction to Kotlin
Introduction to Kotlin
 
Basics of Python programming (part 2)
Basics of Python programming (part 2)Basics of Python programming (part 2)
Basics of Python programming (part 2)
 
Kotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime PerformanceKotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime Performance
 
Programming in Python
Programming in Python Programming in Python
Programming in Python
 
PPT on Data Science Using Python
PPT on Data Science Using PythonPPT on Data Science Using Python
PPT on Data Science Using Python
 
Comparing JVM languages
Comparing JVM languagesComparing JVM languages
Comparing JVM languages
 
Python basics
Python basicsPython basics
Python basics
 
Python Performance 101
Python Performance 101Python Performance 101
Python Performance 101
 
python.ppt
python.pptpython.ppt
python.ppt
 
Euro python2011 High Performance Python
Euro python2011 High Performance PythonEuro python2011 High Performance Python
Euro python2011 High Performance Python
 
Odessapy2013 - Graph databases and Python
Odessapy2013 - Graph databases and PythonOdessapy2013 - Graph databases and Python
Odessapy2013 - Graph databases and Python
 
SQL Server Select Topics
SQL Server Select TopicsSQL Server Select Topics
SQL Server Select Topics
 
Python tour
Python tourPython tour
Python tour
 
15. Streams Files and Directories
15. Streams Files and Directories 15. Streams Files and Directories
15. Streams Files and Directories
 

Similar to Coding in Kotlin with Arrow NIDC 2018

Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojureAbbas Raza
 
A Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingA Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingGarth Gilmour
 
Session 02 python basics
Session 02 python basicsSession 02 python basics
Session 02 python basicsbodaceacat
 
Session 02 python basics
Session 02 python basicsSession 02 python basics
Session 02 python basicsSara-Jayne Terp
 
Functions, List and String methods
Functions, List and String methodsFunctions, List and String methods
Functions, List and String methodsPranavSB
 
A quick and fast intro to Kotlin
A quick and fast intro to Kotlin A quick and fast intro to Kotlin
A quick and fast intro to Kotlin XPeppers
 
Python Interview Questions | Python Interview Questions And Answers | Python ...
Python Interview Questions | Python Interview Questions And Answers | Python ...Python Interview Questions | Python Interview Questions And Answers | Python ...
Python Interview Questions | Python Interview Questions And Answers | Python ...Simplilearn
 
Privet Kotlin (Windy City DevFest)
Privet Kotlin (Windy City DevFest)Privet Kotlin (Windy City DevFest)
Privet Kotlin (Windy City DevFest)Cody Engel
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Introthnetos
 
The Ring programming language version 1.7 book - Part 43 of 196
The Ring programming language version 1.7 book - Part 43 of 196The Ring programming language version 1.7 book - Part 43 of 196
The Ring programming language version 1.7 book - Part 43 of 196Mahmoud Samir Fayed
 
The Ring programming language version 1.5.1 book - Part 13 of 180
The Ring programming language version 1.5.1 book - Part 13 of 180The Ring programming language version 1.5.1 book - Part 13 of 180
The Ring programming language version 1.5.1 book - Part 13 of 180Mahmoud Samir Fayed
 
A Gentle Introduction to Coding ... with Python
A Gentle Introduction to Coding ... with PythonA Gentle Introduction to Coding ... with Python
A Gentle Introduction to Coding ... with PythonTariq Rashid
 
Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)
Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)
Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)Andrés Viedma Peláez
 

Similar to Coding in Kotlin with Arrow NIDC 2018 (20)

Dynamic Python
Dynamic PythonDynamic Python
Dynamic Python
 
BDACA1617s2 - Lecture 2
BDACA1617s2 - Lecture 2BDACA1617s2 - Lecture 2
BDACA1617s2 - Lecture 2
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
 
A Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingA Sceptical Guide to Functional Programming
A Sceptical Guide to Functional Programming
 
Session 02 python basics
Session 02 python basicsSession 02 python basics
Session 02 python basics
 
Session 02 python basics
Session 02 python basicsSession 02 python basics
Session 02 python basics
 
2015 555 kharchenko_ppt
2015 555 kharchenko_ppt2015 555 kharchenko_ppt
2015 555 kharchenko_ppt
 
Functions, List and String methods
Functions, List and String methodsFunctions, List and String methods
Functions, List and String methods
 
BDACA1516s2 - Lecture2
BDACA1516s2 - Lecture2BDACA1516s2 - Lecture2
BDACA1516s2 - Lecture2
 
BD-ACA week2
BD-ACA week2BD-ACA week2
BD-ACA week2
 
A quick and fast intro to Kotlin
A quick and fast intro to Kotlin A quick and fast intro to Kotlin
A quick and fast intro to Kotlin
 
Python Interview Questions | Python Interview Questions And Answers | Python ...
Python Interview Questions | Python Interview Questions And Answers | Python ...Python Interview Questions | Python Interview Questions And Answers | Python ...
Python Interview Questions | Python Interview Questions And Answers | Python ...
 
Privet Kotlin (Windy City DevFest)
Privet Kotlin (Windy City DevFest)Privet Kotlin (Windy City DevFest)
Privet Kotlin (Windy City DevFest)
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Intro
 
BDACA - Lecture2
BDACA - Lecture2BDACA - Lecture2
BDACA - Lecture2
 
The Ring programming language version 1.7 book - Part 43 of 196
The Ring programming language version 1.7 book - Part 43 of 196The Ring programming language version 1.7 book - Part 43 of 196
The Ring programming language version 1.7 book - Part 43 of 196
 
The Ring programming language version 1.5.1 book - Part 13 of 180
The Ring programming language version 1.5.1 book - Part 13 of 180The Ring programming language version 1.5.1 book - Part 13 of 180
The Ring programming language version 1.5.1 book - Part 13 of 180
 
A Gentle Introduction to Coding ... with Python
A Gentle Introduction to Coding ... with PythonA Gentle Introduction to Coding ... with Python
A Gentle Introduction to Coding ... with Python
 
05io
05io05io
05io
 
Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)
Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)
Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)
 

More from Garth Gilmour

Kotlin / Android Update
Kotlin / Android UpdateKotlin / Android Update
Kotlin / Android UpdateGarth Gilmour
 
TypeScript Vs. KotlinJS
TypeScript Vs. KotlinJSTypeScript Vs. KotlinJS
TypeScript Vs. KotlinJSGarth Gilmour
 
Shut Up And Eat Your Veg
Shut Up And Eat Your VegShut Up And Eat Your Veg
Shut Up And Eat Your VegGarth Gilmour
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerGarth Gilmour
 
A TypeScript Fans KotlinJS Adventures
A TypeScript Fans KotlinJS AdventuresA TypeScript Fans KotlinJS Adventures
A TypeScript Fans KotlinJS AdventuresGarth Gilmour
 
The Heat Death Of Enterprise IT
The Heat Death Of Enterprise ITThe Heat Death Of Enterprise IT
The Heat Death Of Enterprise ITGarth Gilmour
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerGarth Gilmour
 
Type Driven Development with TypeScript
Type Driven Development with TypeScriptType Driven Development with TypeScript
Type Driven Development with TypeScriptGarth Gilmour
 
Generics On The JVM (What you don't know will hurt you)
Generics On The JVM (What you don't know will hurt you)Generics On The JVM (What you don't know will hurt you)
Generics On The JVM (What you don't know will hurt you)Garth Gilmour
 
Using Kotlin, to Create Kotlin, to Teach Kotlin, in Space
Using Kotlin, to Create Kotlin,to Teach Kotlin,in SpaceUsing Kotlin, to Create Kotlin,to Teach Kotlin,in Space
Using Kotlin, to Create Kotlin, to Teach Kotlin, in SpaceGarth Gilmour
 
Is Software Engineering A Profession?
Is Software Engineering A Profession?Is Software Engineering A Profession?
Is Software Engineering A Profession?Garth Gilmour
 
Social Distancing is not Behaving Distantly
Social Distancing is not Behaving DistantlySocial Distancing is not Behaving Distantly
Social Distancing is not Behaving DistantlyGarth Gilmour
 
The Great Scala Makeover
The Great Scala MakeoverThe Great Scala Makeover
The Great Scala MakeoverGarth Gilmour
 
Transitioning Android Teams Into Kotlin
Transitioning Android Teams Into KotlinTransitioning Android Teams Into Kotlin
Transitioning Android Teams Into KotlinGarth Gilmour
 
Simpler and Safer Java Types (via the Vavr and Lambda Libraries)
Simpler and Safer Java Types (via the Vavr and Lambda Libraries)Simpler and Safer Java Types (via the Vavr and Lambda Libraries)
Simpler and Safer Java Types (via the Vavr and Lambda Libraries)Garth Gilmour
 
The Three Horse Race
The Three Horse RaceThe Three Horse Race
The Three Horse RaceGarth Gilmour
 
The Bestiary of Pure Functional Programming
The Bestiary of Pure Functional Programming The Bestiary of Pure Functional Programming
The Bestiary of Pure Functional Programming Garth Gilmour
 
BelTech 2019 Presenters Workshop
BelTech 2019 Presenters WorkshopBelTech 2019 Presenters Workshop
BelTech 2019 Presenters WorkshopGarth Gilmour
 
Kotlin The Whole Damn Family
Kotlin The Whole Damn FamilyKotlin The Whole Damn Family
Kotlin The Whole Damn FamilyGarth Gilmour
 

More from Garth Gilmour (20)

Compose in Theory
Compose in TheoryCompose in Theory
Compose in Theory
 
Kotlin / Android Update
Kotlin / Android UpdateKotlin / Android Update
Kotlin / Android Update
 
TypeScript Vs. KotlinJS
TypeScript Vs. KotlinJSTypeScript Vs. KotlinJS
TypeScript Vs. KotlinJS
 
Shut Up And Eat Your Veg
Shut Up And Eat Your VegShut Up And Eat Your Veg
Shut Up And Eat Your Veg
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin Compiler
 
A TypeScript Fans KotlinJS Adventures
A TypeScript Fans KotlinJS AdventuresA TypeScript Fans KotlinJS Adventures
A TypeScript Fans KotlinJS Adventures
 
The Heat Death Of Enterprise IT
The Heat Death Of Enterprise ITThe Heat Death Of Enterprise IT
The Heat Death Of Enterprise IT
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin Compiler
 
Type Driven Development with TypeScript
Type Driven Development with TypeScriptType Driven Development with TypeScript
Type Driven Development with TypeScript
 
Generics On The JVM (What you don't know will hurt you)
Generics On The JVM (What you don't know will hurt you)Generics On The JVM (What you don't know will hurt you)
Generics On The JVM (What you don't know will hurt you)
 
Using Kotlin, to Create Kotlin, to Teach Kotlin, in Space
Using Kotlin, to Create Kotlin,to Teach Kotlin,in SpaceUsing Kotlin, to Create Kotlin,to Teach Kotlin,in Space
Using Kotlin, to Create Kotlin, to Teach Kotlin, in Space
 
Is Software Engineering A Profession?
Is Software Engineering A Profession?Is Software Engineering A Profession?
Is Software Engineering A Profession?
 
Social Distancing is not Behaving Distantly
Social Distancing is not Behaving DistantlySocial Distancing is not Behaving Distantly
Social Distancing is not Behaving Distantly
 
The Great Scala Makeover
The Great Scala MakeoverThe Great Scala Makeover
The Great Scala Makeover
 
Transitioning Android Teams Into Kotlin
Transitioning Android Teams Into KotlinTransitioning Android Teams Into Kotlin
Transitioning Android Teams Into Kotlin
 
Simpler and Safer Java Types (via the Vavr and Lambda Libraries)
Simpler and Safer Java Types (via the Vavr and Lambda Libraries)Simpler and Safer Java Types (via the Vavr and Lambda Libraries)
Simpler and Safer Java Types (via the Vavr and Lambda Libraries)
 
The Three Horse Race
The Three Horse RaceThe Three Horse Race
The Three Horse Race
 
The Bestiary of Pure Functional Programming
The Bestiary of Pure Functional Programming The Bestiary of Pure Functional Programming
The Bestiary of Pure Functional Programming
 
BelTech 2019 Presenters Workshop
BelTech 2019 Presenters WorkshopBelTech 2019 Presenters Workshop
BelTech 2019 Presenters Workshop
 
Kotlin The Whole Damn Family
Kotlin The Whole Damn FamilyKotlin The Whole Damn Family
Kotlin The Whole Damn Family
 

Recently uploaded

Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfIdiosysTechnologies1
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfLivetecs LLC
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commercemanigoyal112
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....kzayra69
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 

Recently uploaded (20)

Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdf
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdf
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commerce
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 

Coding in Kotlin with Arrow NIDC 2018

  • 1. training@instil.co June 2018 © Instil Software 2018 Coding in Kotlin with Arrow NIDC 2018 https://gitlab.com/instil-training/nidc-arrow-2018
  • 2. About Me Experienced trainer • 20 years in the trenches • Over 1000 deliveries The day job • Head of Learning at Instil • Coaching, mentoring etc… The night job(s) • Husband and father • Krav Maga Instructor
  • 3. A quick Kotlin refresher • Kotlin compared to Java Introducing Arrow • What is it and why does it matter? Arrow Pt1: Data Types • Option, Try, Either and Validated Arrow Pt2: Enhanced FP • Partial Invocation, Currying and Composition Arrow Pt3: Esoteric Stuff • Lenses, IO etc… Agenda For This Talk
  • 4. • A Quick Language Overview Kotlin Refresher
  • 5. Enter some numbers or three 'X' to finish 10 20 30 40 50 XXX Total of numbers is: 150 Enter some numbers or three 'X' to finish wibble Ignoring wibble 12 13 14 XXX Total of numbers is: 39 Enter some numbers or three 'X' to finish XXX Total of numbers is: 0
  • 6. public class Program { public static void main(String[] args) { @SuppressWarnings("resource") Scanner scanner = new Scanner(System.in); List<Integer> numbers = new ArrayList<>(); System.out.println("Enter some numbers or three 'X' to finish"); Pattern endOfInput = Pattern.compile("X{3}"); while(scanner.hasNextLine()) { if (scanner.hasNext(endOfInput)) { break; } else if (scanner.hasNextInt()) { numbers.add(scanner.nextInt()); } else { String mysteryText = scanner.nextLine(); System.out.printf("Ignoring %sn", mysteryText); } } int total = numbers.stream().reduce((a,b) -> a + b).orElse(0); System.out.printf("Total of numbers is: %sn",total); } } A Sample Java Program
  • 7. fun main(args: Array<String>) { val numbers = mutableListOf<Int>() val scanner = Scanner(System.`in`) val endOfInput = Regex("X{3}") println("Enter some numbers or three 'X' to finish") while (scanner.hasNextLine()) { if (scanner.hasNext(endOfInput.toPattern())) { break } else if (scanner.hasNextInt()) { numbers += scanner.nextInt() } else { val mysteryText = scanner.nextLine() println("Ignoring $mysteryText") } } //Would be better to use ‘numbers.sum()’ val total = numbers.fold(0, Int::plus) println("Total of numbers is: $total") } The Sample Re-Written in Kotlin Points to note:  No redundant class  No semi-colons  Type inference  Both ‘val’ and ‘var’  Helper functions  String interpolation  Simplified collections  Interop with Java types  Simpler use of FP
  • 8. • What is it? • Why does it matter? Introducing Arrow
  • 9. Languages Today Are Converging
  • 10. The Great Scala vs. Kotlin Debate I am an Enterprise Coder. Like my father before me You fool. If only you knew the power of Monads!
  • 11. How Much Functional Programming is ‘Just Right’?
  • 13. Arrow is a functional programming library for Kotlin coders • Launched in Jan when the two leading libraries joined forces • To prevent the ‘Scalaz vs. Cats’ debate that exists in Scala It is not a formal part of the Kotlin environment • But is generating a lot of interest in the Kotlin community • It has resulted in proposals for changes to the language Learning Arrow can be a bit frustrating as: • The documentation is incomplete and patchy • Changes are still occurring between releases • Sample code is hard to find…. I’m still learning what its all about! • This is very much a report on my progress so far… Introducing Arrow
  • 14. Part One: Data Types
  • 15. Lets Do The Same Thing Many Times 
  • 17. fun readPropertyA(name: String): Option<String> { val result = System.getProperty(name) return if(result != null) Some(result) else None } fun readPropertyB(name: String) = Option.fromNullable(System.getProperty(name)) Reading Property Values Safely Via Option <<abstract>> Option Some None Empty SetSet of One
  • 18. fun print1(input: Option<String>): Unit { when(input) { is None -> println("Nothing was found") is Some -> println("'${input.t}' was found") } } fun print2(input: Option<String>): Unit { println("${input.getOrElse { "Nothing" }} was found") } Reading Property Values Safely Via Option
  • 19. fun print3(input: Option<String>): Unit { val result = input.fold({ "Nothing" }, { it }) println("$result was found") } fun print4(input1: Option<String>, input2: Option<String>): Unit { val result = input1.flatMap { first -> input2.map { second -> "$first and $second" } } println("Results are ${result.getOrElse { "Nothing" }}") } Reading Property Values Safely Via Option
  • 20. fun main(args: Array<String>) { print1(readPropertyA("java.version")) print1(readPropertyA("wibble")) printLine() print2(readPropertyB("java.version")) print2(readPropertyB("wibble")) printLine() print3(readPropertyA("java.version")) print3(readPropertyA("wibble")) printLine() print4( readPropertyA("java.version"), readPropertyB("java.version") ) printLine() print4( readPropertyA("java.version"), readPropertyB("wibble") ) printLine() print4(readPropertyA("wibble"), readPropertyB("wibble")) printLine() print4(readPropertyA("wibble"), readPropertyB("wibble")) } Reading Property Values Safely Via Option
  • 21. Reading Property Values Safely Via Option '1.8.0_121' was found Nothing was found --------------- 1.8.0_121 was found Nothing was found --------------- 1.8.0_121 was found Nothing was found --------------- Results are 1.8.0_121 and 1.8.0_121 --------------- Results are Nothing --------------- Results are Nothing --------------- Results are Nothing
  • 22. class Postcode(val input: String?) { fun value() = Option.fromNullable(input) } class Address(val street: String, val postcode: Postcode?) { fun location() = Option.fromNullable(postcode) } class Person(val name: String, val address: Address?) { fun residence() = Option.fromNullable(address) } Using Option as a Monad
  • 23. fun printPostcode(person: Person) { val result = Option.monad().binding { val address = person.residence().bind() val location = address.location().bind() location.value().bind() }.fix() println(result.fold( { "No postcode available" }, { "Postcode of $it" })) } Using Option as a Monad
  • 24. fun main(args: Array<String>) { printPostcode(Person("Dave", Address("10 Arcatia Road", Postcode("ABC 123")))) printPostcode(Person("Dave", Address("10 Arcatia Road", null))) printPostcode(Person("Dave", null)) } Using Option as a Monad Postcode of ABC 123 No postcode available No postcode available
  • 25. Try
  • 26. fun firstLine(path: String): Try<String> { fun readFirstLine(path: String): String { val reader = BufferedReader(FileReader(path)) return reader.use { it.readLine() } } return Try { readFirstLine(path) } } Reading the First Line from a File via Try <<abstract>> Try Success Failure Holds ErrorHolds Result
  • 27. fun print1(input: Try<String>): Unit { when(input) { is Success -> println("Read '${input.value}'") is Failure -> println("Threw '${input.exception.message}'") } } fun print2(input: Try<String>): Unit { val result = input.fold( { "Threw '${it.message}'" }, { "Read '$it'" }) println(result) } fun print3(input: Try<String>): Unit { input.map { println("Read '$it'") } input.recover { println("Threw '${it.message}'") } } Reading the First Line from a File via Try
  • 28. Lets Have Some Fun 
  • 29. fun print4(input: String) { fun fullPath(str: String) = "data/$str" val finalResult = firstLine(fullPath(input)).flatMap { one -> firstLine(fullPath(one)).flatMap { two -> firstLine(fullPath(two)).flatMap { three -> firstLine(fullPath(three)).flatMap { four -> firstLine(fullPath(four)).map { result -> result } } } } } val message = finalResult.fold({ it.message }, { it }) println("Path navigation produced '$message'") } Traversing Across Files
  • 30. fun main(args: Array<String>) { print1(firstLine("data/input4.txt")) print1(firstLine("foobar.txt")) printLine() print2(firstLine("data/input4.txt")) print2(firstLine("foobar.txt")) printLine() print3(firstLine("data/input4.txt")) print3(firstLine("foobar.txt")) printLine() print4("input.txt") print4("foobar.txt") } Reading the First Line from a File via Try
  • 31. Traversing Across Files Read 'Fortune favors the prepared mind' Threw 'foobar.txt (No such file or directory)' --------------- Read 'Fortune favors the prepared mind' Threw 'foobar.txt (No such file or directory)' --------------- Read 'Fortune favors the prepared mind' Threw 'foobar.txt (No such file or directory)' --------------- Path navigation produced 'Fortune favors the prepared mind' Path navigation produced 'data/foobar.txt (No such file or directory)'
  • 32. fun readFromFiles(input: String): String? { val result = Try.monad().binding { val one = firstLine(fullPath(input)).bind() val two = firstLine(fullPath(one)).bind() val three = firstLine(fullPath(two)).bind() val four = firstLine(fullPath(three)).bind() firstLine(fullPath(four)).bind() }.fix() return result.fold({ it.message }, { it }) } Traversing Across Files
  • 33. fun main(args: Array<String>) { println("Path navigation produced '${readFromFiles("input.txt")}'") println("Path navigation produced '${readFromFiles("foobar")}'") } Traversing Across Files Path navigation produced 'Fortune favors the prepared mind' Path navigation produced 'data/foobar (No such file or directory)'
  • 35. fun genNumber() : Either<Int, Int> { val number = (random() * 100).toInt() return if(number % 2 == 0) Right(number) else Left(number) } Using the Either Type <<abstract>> Either Left Right Happy PathAlternative
  • 36. fun main(args: Array<String>) { val results = (1 .. 10).map { genNumber().flatMap { first -> genNumber().map { second -> Pair(first, second) } } } results.forEach { result -> val msg = result.fold( { "Odd number $it" }, { "Even numbers ${it.first} and ${it.second}" } ) println(msg) } } Using the Either Type Even numbers 50 and 40 Odd number 77 Even numbers 52 and 32 Odd number 25 Odd number 89 Even numbers 80 and 54 Odd number 65 Odd number 1 Odd number 1 Odd number 33
  • 37. fun checkNum(number:Int) : Either<Int, Int> { return if(number % 2 == 0) Right(number) else Left(number) } class EitherTest : ShouldSpec() { init { should("be able to detect Right") { checkNum(4).shouldBeRight(4) } should("be able to detect Left") { checkNum(5).shouldBeLeft(5) } } } All Arrow Types are Supported in KotlinTest
  • 39. Our Sample Problem Whats your ID? ab12 How old are you? 19 Where do you work? HR Error: Bad ID Whats your ID? AB12 How old are you? 19 Where do you work? IT Result: AB12 of age 19 working in IT Whats your ID? ab12 How old are you? 14 Where do you work? Mars Error: Bad Dept Bad ID Bad Age
  • 40. class Employee(val id: String, val age: Int, val dept: String) { override fun toString() = "$id of age $age working in $dept" } fun askQuestion(question: String): String { println(question) return readLine() ?: "" } Reading and Validating Information <<abstract>> Validated Invalid Valid ResultMessage
  • 41. fun checkID(): Validated<String, String> { val regex = Regex("[A-Z]{2}[0-9]{2}") val response = askQuestion("Whats your ID?") return if(regex.matches(response)) Valid(response) else Invalid("Bad ID") } fun checkAge(): Validated<String, Int> { val response = askQuestion("How old are you?").toInt() return if(response > 16) Valid(response) else Invalid("Bad Age") } fun checkDept(): Validated<String, String> { val depts = listOf("HR", "Sales", "IT") val response = askQuestion("Where do you work?") return if(depts.contains(response)) Valid(response) else Invalid("Bad Dept") } Reading and Validating Information
  • 42. fun main(args: Array<String>) { val sg = object : Semigroup<String> { override fun String.combine(b: String) = "$this $b" } val id = checkID() val age = checkAge() val dept = checkDept() val result = Validated.applicative(sg) .map(id, age, dept, { (a,b,c) -> Employee(a,b,c) }) .fix() println(result.fold({ "Error: $it" }, {"Result: $it"} )) } Reading and Validating Information
  • 43. Using Types In Combination
  • 44. Our example of Validated contained a bug… • We assumed the value given for ‘age’ would be an integer Composing Types Whats your ID? AB12 How old are you? abc Exception in thread "main" java.lang.NumberFormatException: For input string: "abc" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:580) at java.lang.Integer.parseInt(Integer.java:615) at arrow.types.validated.ProgramKt.checkAge(Program.kt:22) at arrow.types.validated.ProgramKt.main(Program.kt:37)
  • 45. fun checkAge(): Validated<String, Int> { val response = askQuestion("How old are you?").toInt() return if(response > 16) Valid(response) else Invalid("Bad Age") } Composing Types
  • 46. We can solve the problem by composing types together • Our methods should return a Try<Validated<T,U>> Composing Types
  • 47. fun checkID(): Try<Validated<String, String>> { val regex = Regex("[A-Z]{2}[0-9]{2}") val response = askQuestion("Whats your ID?") return Try { if(regex.matches(response)) Valid(response) else Invalid("Bad ID") } } fun checkAge(): Try<Validated<String, Int>> { val response = Try { askQuestion("How old are you?").toInt() } return response.map({ num -> if(num > 16) Valid(num) else Invalid("Bad Age")}) } Composing Types
  • 48. fun checkSalary(): Try<Validated<String, Double>> { val response = Try { askQuestion("What is your salary?") .toDouble() } return response.map({ num -> if(num > 15000.0) Valid(num) else Invalid("Bad Salary") }) } fun checkDept(): Try<Validated<String, String>> { val depts = listOf("HR", "Sales", "IT") val response = askQuestion("Where do you work?") return Try { if(depts.contains(response)) Valid(response) else Invalid("Bad Dept") } } Composing Types
  • 49. fun success(emp: Employee) = println("Created $emp") fun exception(ex: Throwable) = println("Exception occurred - ${ex.message}") fun invalid(msg: String?) = println("Validation error occurred - $msg") class Employee(val id: String, val age: Int, val dept: String, val salary: Double) { constructor(t: Tuple4<String,Int,String,Double>) : this(t.a,t.b,t.c,t.d) override fun toString() = "$id of age $age working in $dept earning $salary" } Composing Types
  • 51. fun main(args: Array<String>) { val app = Validated.applicative(object : Semigroup<String> { override fun String.combine(b: String) = "$this $b" }) Try.monad().binding { val id = checkID().bind() val age = checkAge().bind() val dept = checkDept().bind() val salary = checkSalary().bind() app.map(id, age, dept, salary, ::Employee).fix() }.fix().fold( {exception(it)}, {it.fold(::invalid,::success)}) } Composing Types
  • 52. Composing Types Whats your ID? AB12 How old are you? abc Exception occurred - For input string: "abc" Whats your ID? AB12 How old are you? 21 Where do you work? Sales What is your salary? abc Exception occurred - For input string: "abc" Whats your ID? foo How old are you? 21 Where do you work? Sales What is your salary? 30000.0 Validation error occurred - Bad ID Whats your ID? AB12 How old are you? 21 Where do you work? foo What is your salary? 30000.0 Validation error occurred - Bad Dept
  • 53. Composing Types Whats your ID? AB12 How old are you? 21 Where do you work? Sales What is your salary? 30000.0 Created AB12 of age 21 working in Sales earning 30000.0
  • 56. fun demo1() { val addNums = { no1: Int, no2: Int -> println("Adding $no1 to $no2") no1 + no2 } val addSeven = addNums.partially2(7) val result = addSeven(3) println(result) } Partial Invocation Adding 3 to 7 10
  • 57. fun demo2() { val addNums = { no1: Int, no2: Int -> println("Adding $no1 to $no2") no1 + no2 } val addSeven = addNums.partially2(7) val addSevenToThree = addSeven.partially1(3) val result = addSevenToThree() println(result) } Partial Invocation Adding 3 to 7 10
  • 58. fun demo3() { val addNums = { no1: Int, no2: Int -> println("Adding $no1 to $no2") no1 + no2 } val addSeven = addNums.reverse().partially2(7) val result = addSeven(3) println(result) } Partial Invocation Adding 7 to 3 10
  • 59. fun grep(path: String, regex: Regex, action: (String) -> Unit) { val reader = BufferedReader(FileReader(path)) reader.use { it.lines() .filter { regex.matches(it) } .forEach(action) } } val grepLambda = { a: String, b: Regex, c: (String) -> Unit -> grep(a, b, c) } fun printLine() = println("-------------") Here’s Something More Useful
  • 60. val filePath = "data/grepInput.txt" val regex = "[A-Z]{2}[0-9]{2}".toRegex() grep(filePath, regex, ::println) printLine() grepLambda(filePath, regex, ::println) printLine() Here’s Something More Useful AB12 CD34 EF56 ------------- AB12 CD34 EF56 -------------
  • 61. val grepAndPrint = grepLambda.partially3(::println) grepAndPrint(filePath, regex) printLine() val sb = StringBuilder() val grepAndConcat = grepLambda.partially3 {sb.append(it)} grepAndConcat(filePath, regex) println(sb.toString()) printLine() val grepAndPrintRegex = grepAndPrint.partially2(regex) grepAndPrintRegex(filePath) Here’s Something More Useful AB12 CD34 EF56 ------------- AB12CD34EF56 ------------- AB12 CD34 EF56
  • 63. val addThree = { a:Int, b: Int, c:Int -> println("Adding $a, $b and $c") a + b + c } fun printLine() = println("--------------------") fun main(args: Array<String>) { println(addThree(10,20,40)) printLine() val f1 = addThree.curried() val f2 = f1(10) val f3 = f2(20) val result = f3(40) println(result) printLine() println(f1(10)(20)(40)) printLine() val f4 = addThree.reverse().curried() println(f4(10)(20)(40)) println() } The Basic Syntax of Currying Adding 10, 20 and 40 70 -------------------- Adding 10, 20 and 40 70 -------------------- Adding 10, 20 and 40 70 -------------------- Adding 40, 20 and 10 70
  • 64. fun grep(path: String, regex: Regex, action: (String) -> Unit) { val reader = BufferedReader(FileReader(path)) reader.use { it.lines() .filter { regex.matches(it) } .forEach(action) } } val grepLambda = { a: String, b: Regex, c: (String) -> Unit -> grep(a,b,c) } fun printLine() = println("-------------") A More Useful Example
  • 65. fun main(args: Array<String>) { val filePath = "data/grepInput.txt" val regex1 = "[A-Z]{2}[0-9]{2}".toRegex() val regex2 = "[a-z]{2}[0-9]{2}".toRegex() val f1 = grepLambda.curried() val grepInFile = f1(filePath) val grepRegex1 = grepInFile(regex1) val grepRegex2 = grepInFile(regex2) grepRegex1(::println) printLine() grepRegex2(::println) } A More Useful Example AB12 CD34 EF56 ------------- ab12 cd34 ef56
  • 67. val source = { name: String -> "data/$name" } val allLines = { path: String -> val reader = BufferedReader(FileReader(path)) reader.use { it.lines().toList() } } val findMatches = { input: List<String> -> val regex = "[A-Z]{2}[0-9]{2}".toRegex() input.filter(regex::matches) } Composing Functions Together
  • 68. fun main(args: Array<String>) { val composed1 = findMatches compose allLines compose source println(composed1("grepInput.txt")) val composed2 = source forwardCompose allLines forwardCompose findMatches println(composed2("grepInput.txt")) val composed3 = source andThen allLines andThen findMatches println(composed3("grepInput.txt")) } Composing Functions Together [AB12, CD34, EF56] [AB12, CD34, EF56] [AB12, CD34, EF56]
  • 69. Part 3: Weird Stuff
  • 71. @optics data class Postcode(val value: String) { override fun toString() = "$value" } @optics data class Address(val street: String, val postcode: Postcode) { override fun toString() = "$street ($postcode)" } @optics data class Person(val name: String, val address: Address) { override fun toString() = "$name living at $address" } Copying Immutable Structures With Lenses
  • 72. fun main(args: Array<String>) { val oldPerson = Person("Dave", Address("10 Arcatia Road", Postcode("BT26 ABC"))) println(oldPerson) val personAddressPostcode = personAddress() compose addressPostcode() compose postcodeValue() val newPerson = personAddressPostcode.modify(oldPerson, { _ -> "BT37 DEF" }) println(newPerson) } Copying Immutable Structures With Lenses Dave living at 10 Arcatia Road (BT26 ABC) Dave living at 10 Arcatia Road (BT37 DEF)