Slide 1

Slide 1 text

Types Working For You Richard Dallaway, @d6y underscore.io

Slide 2

Slide 2 text

Modern type system with lots of power

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Two Themes Straightforward Scala Types Working for Us

Slide 6

Slide 6 text

Progression Part 1 Straightforward Scala Part 2 Functional Programming Part 3 Typelevel Programming

Slide 7

Slide 7 text

Straightforward Scala — Part 1 —

Slide 8

Slide 8 text

The only problem was we had no idea what the code was doing at first. We came across a strange symbol we hadn’t seen in our projects before The spaceship operator <|*|> Someone said out loud “what the hell is that?” http://jimplush.com/talk/

Slide 9

Slide 9 text

The only problem was we had no idea what the code was doing at first. We came across a strange symbol we hadn’t seen in our projects before The spaceship operator <|*|> Someone said out loud “what the hell is that?” http://jimplush.com/talk/

Slide 10

Slide 10 text

The only problem was we had no idea what the code was doing at first. We came across a strange symbol we hadn’t seen in our projects before The spaceship operator <|*|> Someone said out loud “what the hell is that?” http://jimplush.com/talk/

Slide 11

Slide 11 text

The only problem was we had no idea what the code was doing at first. We came across a strange symbol we hadn’t seen in our projects before The spaceship operator <|*|> Someone said out loud “what the hell is that?” http://jimplush.com/talk/

Slide 12

Slide 12 text

“It’s about having a maintainable code base where you can have 
 people cross projects easily and get new hires up to speed rapidly”

Slide 13

Slide 13 text

Power! Protect the team from it and Get the benefit of it

Slide 14

Slide 14 text

What can we do?

Slide 15

Slide 15 text

1. Expressions, types, & values 2. Objects and classes 3. Algebraic data types 4. Structural recursion 5. Sequencing computation 6. Type classes

Slide 16

Slide 16 text

1. Expressions, types, & values 2. Objects and classes 3. Algebraic data types 4. Structural recursion 5. Sequencing computation 6. Type classes

Slide 17

Slide 17 text

Algebraic data types Structural recursion

Slide 18

Slide 18 text

Algebraic data types data into code Structural recursion transformation

Slide 19

Slide 19 text

Model data with logical ors and logical ands

Slide 20

Slide 20 text

A website visitor is: • anonymous; or • logged in

Slide 21

Slide 21 text

A logged in user has: • an ID; and • facts we know about them

Slide 22

Slide 22 text

Two Patterns and (product types) or (sum types) Sum and product together make algebraic data types

Slide 23

Slide 23 text

Structure of the code follows the structure of the data

Slide 24

Slide 24 text

A website visitor is: • anonymous; or • logged in

Slide 25

Slide 25 text

sealed trait Visitor case class Anonymous()
 extends Visitor case class User()
 extends Visitor

Slide 26

Slide 26 text

A logged in user has: • an ID; and • facts we know about them
 An anonymous has: • an ID

Slide 27

Slide 27 text

sealed trait Visitor case class Anonymous()
 extends Visitor case class User()
 extends Visitor

Slide 28

Slide 28 text

sealed trait Visitor case class Anonymous(id: Id)
 extends Visitor case class User(id: Id, facts: Set[Fact])
 extends Visitor

Slide 29

Slide 29 text

Structural recursion

Slide 30

Slide 30 text

def serveAd(v: Visitor): Advert = ???

Slide 31

Slide 31 text

Structure of the code follows the structure of the data

Slide 32

Slide 32 text

def serveAd(v: Visitor): Advert = ???

Slide 33

Slide 33 text

def serveAd(v: Visitor): Advert = v match { case User(_, info) => relevantAd(info) case Anonymous(id) => adRotation(id) }

Slide 34

Slide 34 text

def serveAd(v: Visitor): Advert = v match { case User(_, info) => relevantAd(info) case Anonymous(id) => adRotation(id) }

Slide 35

Slide 35 text

def serveAd(v: Visitor): Advert = v match { case User(_, info) => relevantAd(info) case Anonymous(id) => adRotation(id) } Structure

Slide 36

Slide 36 text

ADT & Structural Recursion Straightforward part of Scala. Clear, productive, occurs frequently. Be opinionated in what you use. Structure helps us.

Slide 37

Slide 37 text

Help from FP Ideas — Part 2 —

Slide 38

Slide 38 text

Combining lists Concatenating strings Union of sets Combining things in a loop Chaining logical operations Adding numbers Building up a JavaScript expression Showing errors in a UI ...

Slide 39

Slide 39 text

A combine function and an empty value

Slide 40

Slide 40 text

Addition Empty Combine 0 +

Slide 41

Slide 41 text

Set Empty Combine Set.empty union

Slide 42

Slide 42 text

For any T Empty Combine A zero for T A way to combine two Ts and give me back a T

Slide 43

Slide 43 text

A combine function and an empty value

Slide 44

Slide 44 text

Monoid A combine function and an empty value …and laws

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

The boss asks… What’s the total visits to the web site? def report(vs: List[Int]): Int = ???

Slide 47

Slide 47 text

For any T Empty Combine A zero for T A way to combine two Ts and give me back a T

Slide 48

Slide 48 text

For any T trait Monoid[T] { def empty: T def combine(x: T, y: T): T }

Slide 49

Slide 49 text

val addition = new Monoid[Int] { def empty = 0 def combine(x: Int, y: Int) = x+y }

Slide 50

Slide 50 text

fold

Slide 51

Slide 51 text

def fold(vs: List[Int]): Int = vs match { case Nil => 0 case v :: rest => v + fold(rest) } fold(List(1,2,3))
 // 6

Slide 52

Slide 52 text

fold(1,2,3) 1 + fold(2,3) 2 + fold(3) 3 + fold() 0 0 + 3 + 2 + 1 = 6

Slide 53

Slide 53 text

fold(1,2,3) 1 + fold(2,3) 2 + fold(3) 3 + fold() 0 0 + 3 + 2 + 1 = 6

Slide 54

Slide 54 text

fold(1,2,3) 1 + fold(2,3) 2 + fold(3) 3 + fold() 0 0 + 3 + 2 + 1 = 6

Slide 55

Slide 55 text

fold(1,2,3) 1 + fold(2,3) 2 + fold(3) 3 + fold() 0 0 + 3 + 2 + 1 = 6

Slide 56

Slide 56 text

fold(1,2,3) 1 + fold(2,3) 2 + fold(3) 3 + fold() 0 0 + 3 + 2 + 1 = 6

Slide 57

Slide 57 text

fold(1,2,3) 1 + fold(2,3) 2 + fold(3) 3 + fold() 0 0 + 3 + 2 + 1 = 6

Slide 58

Slide 58 text

def fold(vs: List[Int]): Int = vs match { case Nil => 0 case v :: rest => v + fold(rest) } fold(List(1,2,3))
 // 6

Slide 59

Slide 59 text

def fold(vs: List[Int], m: Monoid[Int]): Int = vs match { case Nil => 0 case v :: rest => v + fold(rest) } fold(List(1,2,3), addition)
 // 6

Slide 60

Slide 60 text

def fold(vs: List[Int], m: Monoid[Int]): Int = vs match { case Nil => m.empty case v :: rest => m.combine(v, fold(rest,m)) } fold(List(1,2,3), addition)
 // 6

Slide 61

Slide 61 text

def fold[T](vs: List[T], m: Monoid[T]): T = vs match { case Nil => m.empty case v :: rest => m.combine(v, fold(rest,m)) } fold(List(1,2,3), addition)
 // 6

Slide 62

Slide 62 text

Split on cases, inspect values you have

Slide 63

Slide 63 text

def fold[T](vs: List[T], m: Monoid[T]): T = vs match { case Nil => ??? case v :: rest => ??? } fold(List(1,2,3), addition)
 // 6

Slide 64

Slide 64 text

def fold[T](vs: List[T], m: Monoid[T]): T = vs match { case Nil => m.empty case v :: rest => ??? } fold(List(1,2,3), addition)
 // 6

Slide 65

Slide 65 text

But back to Monoids…

Slide 66

Slide 66 text

The boss asks… What’s the total visits to the web site? def report(vs: List[Int]): Int = fold(vs, addition)

Slide 67

Slide 67 text

Benefits Composition Flexibility Problem Solving

Slide 68

Slide 68 text

The boss asks… How many distinct visitors? def report(vs: List[Visitor]): Int = ???

Slide 69

Slide 69 text

Set Empty Combine Set.empty union

Slide 70

Slide 70 text

The boss says… Argh! 
 The servers are OutOfMemory

Slide 71

Slide 71 text

HyperLogLog Empty Combine new HLL() HLL.plus Armon Dadgar (Papers We Love, 2015)
 “Bloom Filters and HyperLogLog”

Slide 72

Slide 72 text

The boss asks… Who are the really keen 
 visitors to the site?

Slide 73

Slide 73 text

Count-Min Sketch Empty Combine new CMS() CMS.plus Laura Bledaite (Scala eXchange 2015) 
 “Count-Min Sketch in Real Data Applications”

Slide 74

Slide 74 text

We can safely run 
 a parallel version 
 of fold

Slide 75

Slide 75 text

Laws

Slide 76

Slide 76 text

a + 0 = a (a + b) + c = a + (b + c)

Slide 77

Slide 77 text

Identity & Associativity a combine empty = a (a combine b) combine c 
 = a combine (b combine c)

Slide 78

Slide 78 text

a combine b combine combine c d e f

Slide 79

Slide 79 text

No content

Slide 80

Slide 80 text

Errors: 10 Warnings: 0

Slide 81

Slide 81 text

Its a monoid I know this

Slide 82

Slide 82 text

…so we fold

Slide 83

Slide 83 text

Summary Types and laws give us flexibility & help lead us to solutions. They help us every day.

Slide 84

Slide 84 text

A Taste of Typelevel — Part 3 —

Slide 85

Slide 85 text

Date Metric Mon Low Tue High csv( List(“Date”, “Metric”), List( List(“Mon”, “Low”), List(“Tue”, “High”) ) )

Slide 86

Slide 86 text

Date Mon Low Tue High csv( List(“Date”), List( List(“Mon”, “Low”), List(“Tue”, “High”) ) )

Slide 87

Slide 87 text

How can we prevent that error happening again?

Slide 88

Slide 88 text

def csv( hdrs: List[String], rows: List[List[String]] ): String = ???

Slide 89

Slide 89 text

def csv[N <: Nat]( hdrs: List[String], rows: List[List[String]] ): String = ??? import shapeless._ import syntax.sized._

Slide 90

Slide 90 text

def csv[N <: Nat]( hdrs: Sized[List[String], N], rows: List[Sized[List[String], N]] ): String = ??? import shapeless._ import syntax.sized._

Slide 91

Slide 91 text

csv( Sized(“Date”), List( Sized(“Mon”, “Low”), Sized(“Tue”, “High”) ) )

Slide 92

Slide 92 text

csv( Sized(“Date”), List( Sized(“Mon”, “Low”), Sized(“Tue”, “High”) ) ) Sized[List, 1] Sized[List, 2]

Slide 93

Slide 93 text

How? Sized(“Date”) constructs Sized[Nat] Nat implements numbers as types

Slide 94

Slide 94 text

sealed trait Nat trait Succ[P <: Nat] extends Nat trait Zero extends Nat

Slide 95

Slide 95 text

Zero 0 Succ[Zero] 1 Succ[Succ[Zero]] 2 Succ[Succ[Succ[Zero]]] 3

Slide 96

Slide 96 text

sealed trait Nat trait Succ[P <: Nat] extends Nat trait Zero extends Nat

Slide 97

Slide 97 text

sealed trait Nat trait Succ[P <: Nat] extends Nat trait Zero extends Nat type One = Succ[Zero] type Two = Succ[One] implicitly[Succ[Zero] =:= One] implicitly[Succ[One] =:= Succ[Succ[Zero]]]

Slide 98

Slide 98 text

sealed trait Nat trait Succ[P <: Nat] extends Nat trait Zero extends Nat type One = Succ[Zero] type Two = Succ[One] implicitly[Succ[Zero] =:= One] implicitly[Succ[One] =:= Succ[Succ[Zero]]]

Slide 99

Slide 99 text

sealed trait Nat trait Succ[P <: Nat] extends Nat trait Zero extends Nat type One = Succ[Zero] type Two = Succ[One] implicitly[Succ[Zero] =:= One] implicitly[Succ[One] =:= Succ[Succ[Zero]]]

Slide 100

Slide 100 text

sealed trait Nat trait Succ[P <: Nat] extends Nat trait Zero extends Nat type One = Succ[Zero] type Two = Succ[One] implicitly[Succ[Zero] =:= Two] error: Cannot prove that Succ[Zero] =:= Two.

Slide 101

Slide 101 text

Merging Fields

Slide 102

Slide 102 text

case class User(
 id : Long,
 name : String,
 email : Option[String]) val user = User(
 123L, 
 “Bruce Wayne”,
 Some(“[email protected]”))

Slide 103

Slide 103 text

PATCH /user/123 {
 “name” : “Batman”
 }

Slide 104

Slide 104 text

case class User(
 id : Long,
 name : String,
 email : Option[String]) case class Update(
 name : Option[String],
 email : Option[Option[String]])

Slide 105

Slide 105 text

val user = User(
 123L, 
 “Bruce Wayne”,
 Some(“[email protected]”)) val update = Update( 
 Some(“Batman”), 
 None) How do we get to… User(
 123L, 
 “Batman”, 
 Some(“[email protected]”))

Slide 106

Slide 106 text

Bulletin https://github.com/davegurnell/bulletin

Slide 107

Slide 107 text

How? User String Option[String] … Option[String] Option[
 Option[String] ] … Update

Slide 108

Slide 108 text

How? User String Option[String] … Option[String] Option[
 Option[String] ] … Update Head

Slide 109

Slide 109 text

How? User String Option[String] … Option[String] Option[
 Option[String] ] … Update Head The Rest…

Slide 110

Slide 110 text

How? Type constraints Implicit methods HLists Labelled generic Macros …

Slide 111

Slide 111 text

val user = User(
 123L, 
 "Bruce Wayne”,
 Some(“[email protected]”)) val update = Update( 
 Some(“Batman”), 
 None) import bulletin._ val updated = user.merge(update) // User(
 // 123L, 
 // “Batman”, 
 // Some(“[email protected]”))

Slide 112

Slide 112 text

val user = User(
 123L, 
 "Bruce Wayne”,
 Some(“[email protected]”)) val update = Update( 
 Some(“Batman”), 
 None) import bulletin._ val updated = user.merge(update) // User(
 // 123L, 
 // “Batman”, 
 // Some(“[email protected]”))

Slide 113

Slide 113 text

Summary The compiler can help (maybe more than you thought). Reduce boilerplate code.

Slide 114

Slide 114 text

Using Power Tools Can go one of two ways…

Slide 115

Slide 115 text

Using Power Tools Can go one of two ways… What the hell is that? It’s a monoid!
 I know this

Slide 116

Slide 116 text

Simple Types Power Share

Slide 117

Slide 117 text

2008 ‘The name Scala stands for “scalable language.”
 
 The language is so named because it was designed to grow with the demands of its users.’

Slide 118

Slide 118 text

What have we seen? Some straightforward parts of Scala
 —Clear, maintainable, helpful Encoding ideas in types
 —flexibility, leads us to solutions
 
 Let the compiler do it 
 —when it make sense for your demands

Slide 119

Slide 119 text

Summary Scala scaling with your needs
 —be opinionated in what you use, more when needed Types working for us, not stopping us
 —functional programming, share what you learn

Slide 120

Slide 120 text

Thanks! Richard Dallaway, @d6y underscore.io

Slide 121

Slide 121 text

Thanks! Richard Dallaway, @d6y underscore.io Amanda Laucher Wesley Reisz Noel Welsh Dave Gurnell Miles Sabin Jono Ferguson Julio Capote Alessandro Zoffoli