Functional Programming with Λrrow
• Data Types
• Optics
• Error Handling
• Type Classes
• Types of Polymorphism
• Ad-hoc Polymorphism
• Type classes proposal for Kotlin
Slide 5
Slide 5 text
Optics
Iso
Lens
Slide 6
Slide 6 text
Optics
Iso
Lens
Slide 7
Slide 7 text
data class Point2D
data class Cords
(val x: Int, val y: Int)
Isomorphism
(val x: Int, val y: Int)
Slide 8
Slide 8 text
data class Point2D
data class Cords
(val x: Int, val y: Int)
Isomorphism
(val x: Int, val y: Int)
Slide 9
Slide 9 text
data class Point2D
data class Cords
(val x: Int, val y: Int)
Isomorphism
(val x: Int, val y: Int)
fun point2DToCords (point2D: Point2D): Cords {
return Cords(point2D.x, point2D.y)
}
Slide 10
Slide 10 text
data class Point2D
data class Cords
(val x: Int, val y: Int)
Isomorphism
(val x: Int, val y: Int)
fun cordsToPoint2D (cord: Cord): Point2D {
return Point2D(cord.x, cord.y)
}
Isomorphism
Source:
Focus:
f ≇ g = IdA
g ≇ f = IdS
f: "->
g: "->
S
A
S A
A S
Slide 13
Slide 13 text
Isomorphism
interface Iso {
/**
* Get the focus of a [Iso]
"*/
fun get(s: S): A
/**
* Get the modified focus of a [Iso]
"*/
fun reverseGet(b: B): T
}
Slide 14
Slide 14 text
Isomorphism
val pointIsoCords : Iso =
Iso(
get = { point !-> Cords(point.x, point.y) },
reverseGet = { cords !-> Point2D(cords.x, cords.y) }
)
Slide 15
Slide 15 text
Isomorphism
val point = Point2D(6, 10)
val cords: Cords = pointIsoCords.get(point)
"// Cords(6, 10)
Slide 16
Slide 16 text
Isomorphism
val cords = Cords(6, 10)
val point2D: Point2D = pointIsoCords.reverseGet(cords)
"// Point2D(6, 10)
Slide 17
Slide 17 text
data class Point2D
data class Tuple2
(val x: Int, val y: Int)
Isomorphism
(val x: Int, val y: Int)
Slide 18
Slide 18 text
data class Tuple2(val a: A, val b: B)
Isomorphism
data class Tuple3(val a: A,
val b: B,
val c: C)
data class Tuple4("..)
Slide 19
Slide 19 text
val pointIsoTuple: Iso> =
Iso(
get = { point !-> point.x toT point.y },
reverseGet = { tuple !-> Point2D(tuple.a, tuple.b) }
)
Isomorphism
Slide 20
Slide 20 text
var point2D = Point2D(1, 2)
val tuple2 = pointIsoTuple.get(point2D)
"// Tuple2(a=1, b=2)
val point2D = pointIsoTuple.reverseGet(tuple2)
"// Point2D(x=1, y=2)
Isomorphism
Slide 21
Slide 21 text
val pointIsoTuple = Iso(
get = { point !-> Tuple2(point.x, point.y) },
reverseGet = { tuple !-> Point2D(tuple.a, tuple.b) }
)
Generating Isomorphism
data class Point2D (val x: Int, val y: Int)
Slide 22
Slide 22 text
@Retention(SOURCE)
@Target(CLASS)
annotation class isos
Generating Isomorphism
Slide 23
Slide 23 text
Generating Isomorphism
@isos data class Point2D (val x: Int, val y: Int)
Slide 24
Slide 24 text
Optics
Iso
Lens
Slide 25
Slide 25 text
Lens
Source: S
Purpose: Set, Get, Copy an immutable data structure
through functional references.
Slide 26
Slide 26 text
Lens
Lens
Get : S "-> A
Set : A "-> (S "-> S)
Slide 27
Slide 27 text
Lens
data class Person(val name: String, val age: Int)
Slide 28
Slide 28 text
Lens
data class Person(val name: String, val age: Int)
val personNameLens : Lens = Lens(
get = { person !-> person.name },
set = { newName !-> {foo !-> foo.copy(name = newName)} }
)
Slide 29
Slide 29 text
Lens
val person = Person("John Doe", 100)
val personNameLens : Lens = Lens(
get = { person !-> person.name },
set = { newName !-> {foo !-> foo.copy(name = newName)} }
)
Slide 30
Slide 30 text
Lens
val person = Person("John Doe", 100)
val newPerson = personNameLens.set(person, "John Doe Jr”)
// Person(name=John Doe Jr, age=100)
Slide 31
Slide 31 text
Lens
data class Employee(val name: String, val company: Company)
data class Company(val name: String, val address: Address)
data class Address(val city: String, val street: Street)
data class Street(val number: Int, val name: String)
Slide 32
Slide 32 text
Lens
val street = Street(1, "hacker Way”)
val address = Address("Menlo Park, CA", street)
val company = Company("Facebook", address)
val employee = Employee("John Doe", company)
Slide 33
Slide 33 text
Lens
employee.copy(
company = employee.company.copy(
address = employee.company.address.copy(
street = employee.company.address.street.copy(
name = employee.company.address.street.name.capitalize()
)
)
)
)
Slide 34
Slide 34 text
Lens
data class Street(val number: Int, val name: String)
data class Employee(val name: String, val company: Company)
Slide 35
Slide 35 text
val company: Company)
Lens
data class Employee(val name: String, val company: Company)
val employeeCompany: Lens =
Lens(get = { it.company },
set = { company !->
{ employee !->
employee.copy(company = company)
}
}
)
Slide 36
Slide 36 text
data class Company(val name: String, val address: Address)
Lens
val companyAddress: Lens =
Lens(
get = { it.address },
set = { address !->
{ company !->
company.copy(address = address)
}
})
val address: Address)
Slide 37
Slide 37 text
data class Address(val city: String, val street: Street)
Lens
val addressStreet: Lens =
Lens(
get = { it.street },
set = { street !-> {
address !->
address.copy(street = street)
}
})
val street: Street)
Slide 38
Slide 38 text
data class Street(val number: Int, val name: String)
Lens
val streetName: Lens = Lens(
get = { it.name },
set = { name !-> { street !-> street.copy(name = name) } }
)
val name: String)
Ad-hoc Polymorphism
fun combineAll(a: Matrix, b: Matrix) : Matrix {
return doMatrixComputation()
}
• Same name with different implementation.
• Type Dependent.
fun combineAll(a: String, b: String) : String {
return a + b
}
Slide 81
Slide 81 text
Ad-hoc Polymorphism with Type Class
inline fun combineAll(
a: F, b: F,
ev: Monoid = monoidal()
): F {
return ev.combine(a, b)
}
• Polymorphism with Type Classes.
• How do I achieve this?
Slide 82
Slide 82 text
Define Type Class
interface Monoid {
fun combine(a: F, b: F): F
}
Slide 83
Slide 83 text
Define Type Class
interface Monoid {
fun combine(a: F, b: F): F
}
val monoidMap = mutableMapOf, Monoid"<*">>()
Slide 84
Slide 84 text
Define Instances of Type Class
val monoidMap = mutableMapOf, Monoid"<*">>()
monoidMap[String"::class.java] = object: Monoid {
override fun combine(a: String, b: String): String {
return a + b
}
}
Slide 85
Slide 85 text
Define Instances of Type Class
val monoidMap = mutableMapOf, Monoid"<*">>()
monoidMap[Matrix"::class.java] = object: Monoid {
override fun combine(a: Matrix, b: Matrix): Matrix {
return addMatricies(a, b)
}
}
Slide 86
Slide 86 text
Getting Instances of Type Class
val monoidMap = mutableMapOf, Monoid"<*">>()
inline fun monoidal(): Monoid {
return monoidMap[F"::class.java] as Monoid
}
Slide 87
Slide 87 text
Ad-hoc Polymorphism with Type Class
inline fun combineAll(
a: F, b: F,
ev: Monoid = monoidal()
): F {
return ev.combine(a, b)
}
Slide 88
Slide 88 text
Ad-hoc Polymorphism with Type Class
inline fun combineAll(
a: F, b: F,
ev: Monoid = monoidal()
): F {
return ev.combine(a, b)
}
combineAll(matrix, matrix)
combineAll("Hello", "World")
Slide 89
Slide 89 text
Type Classes in Λrrow
@typeclass
interface Functor : TC {
fun map(fa: HK, f: (A) -> B): HK
}