Types Working For You Richard Dallaway, @d6y underscore.io Modern - - PowerPoint PPT Presentation

types working for you
SMART_READER_LITE
LIVE PREVIEW

Types Working For You Richard Dallaway, @d6y underscore.io Modern - - PowerPoint PPT Presentation

Types Working For You Richard Dallaway, @d6y underscore.io Modern type system with lots of power Two Themes Straightforward Scala Types Working for Us Progression Part 1 Straightforward Scala Part 2 Functional Programming Part 3


slide-1
SLIDE 1

Types Working For You

Richard Dallaway, @d6y

underscore.io

slide-2
SLIDE 2

Modern type system with lots of power

slide-3
SLIDE 3
slide-4
SLIDE 4
slide-5
SLIDE 5

Two Themes

Straightforward Scala Types Working for Us

slide-6
SLIDE 6

Progression

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

slide-7
SLIDE 7

Straightforward Scala

— Part 1 —

slide-8
SLIDE 8

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

  • ur projects before

The spaceship operator <|*|> Someone said out loud “what the hell is that?”

http://jimplush.com/talk/

slide-9
SLIDE 9

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

  • ur projects before

The spaceship operator <|*|> Someone said out loud “what the hell is that?”

http://jimplush.com/talk/

slide-10
SLIDE 10

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

  • ur projects before

The spaceship operator <|*|> Someone said out loud “what the hell is that?”

http://jimplush.com/talk/

slide-11
SLIDE 11

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

  • ur projects before

The spaceship operator <|*|> Someone said out loud “what the hell is that?”

http://jimplush.com/talk/

slide-12
SLIDE 12

“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

Power!

Protect the team from it and Get the benefit of it

slide-14
SLIDE 14

What can we do?

slide-15
SLIDE 15
  • 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
  • 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

Algebraic data types Structural recursion

slide-18
SLIDE 18

Algebraic data types

data into code

Structural recursion transformation

slide-19
SLIDE 19

Model data with logical

  • rs and logical ands
slide-20
SLIDE 20

A website visitor is:

  • anonymous; or
  • logged in
slide-21
SLIDE 21

A logged in user has:

  • an ID; and
  • facts we know about

them

slide-22
SLIDE 22

Two Patterns and (product types)

  • r (sum types)

Sum and product together make algebraic data types

slide-23
SLIDE 23

Structure of the code follows the structure of the data

slide-24
SLIDE 24

A website visitor is:

  • anonymous; or
  • logged in
slide-25
SLIDE 25

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

slide-26
SLIDE 26

A logged in user has:

  • an ID; and
  • facts we know about

them
 An anonymous has:

  • an ID
slide-27
SLIDE 27

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

slide-28
SLIDE 28

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

slide-29
SLIDE 29

Structural recursion

slide-30
SLIDE 30

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

slide-31
SLIDE 31

Structure of the code follows the structure of the data

slide-32
SLIDE 32

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

slide-33
SLIDE 33

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

slide-34
SLIDE 34

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

slide-35
SLIDE 35

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

Structure

slide-36
SLIDE 36

ADT & Structural Recursion

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

slide-37
SLIDE 37

Help from FP Ideas

— Part 2 —

slide-38
SLIDE 38

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

A combine function and an empty value

slide-40
SLIDE 40

Addition

Empty Combine +

slide-41
SLIDE 41

Set

Empty Combine Set.empty union

slide-42
SLIDE 42

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

A combine function and an empty value

slide-44
SLIDE 44

Monoid A combine function and an empty value …and laws

slide-45
SLIDE 45
slide-46
SLIDE 46

The boss asks…

What’s the total visits to the web site?

def report(vs: List[Int]): Int = ???

slide-47
SLIDE 47

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

For any T

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

slide-49
SLIDE 49

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

slide-50
SLIDE 50

fold

slide-51
SLIDE 51

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

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

slide-53
SLIDE 53

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

slide-54
SLIDE 54

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

slide-55
SLIDE 55

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

slide-56
SLIDE 56

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

slide-57
SLIDE 57

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

slide-58
SLIDE 58

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

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

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

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

Split on cases, inspect values you have

slide-63
SLIDE 63

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

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

But back to Monoids…

slide-66
SLIDE 66

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

Benefits Composition Flexibility Problem Solving

slide-68
SLIDE 68

The boss asks…

How many distinct visitors?

def report(vs: List[Visitor]): Int = ???

slide-69
SLIDE 69

Set

Empty Combine Set.empty union

slide-70
SLIDE 70

The boss says…

Argh! 
 The servers are OutOfMemory

slide-71
SLIDE 71

HyperLogLog

Empty Combine new HLL() HLL.plus

Armon Dadgar (Papers We Love, 2015)
 “Bloom Filters and HyperLogLog”

slide-72
SLIDE 72

The boss asks…

Who are the really keen 
 visitors to the site?

slide-73
SLIDE 73

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

We can safely run 
 a parallel version 


  • f fold
slide-75
SLIDE 75

Laws

slide-76
SLIDE 76

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

slide-77
SLIDE 77

Identity & Associativity

a combine empty = a (a combine b) combine c 
 = a combine (b combine c)

slide-78
SLIDE 78

a combine b combine combine c d e f

slide-79
SLIDE 79
slide-80
SLIDE 80

Errors: 10 Warnings: 0

slide-81
SLIDE 81

Its a monoid I know this

slide-82
SLIDE 82

…so we fold

slide-83
SLIDE 83

Summary

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

slide-84
SLIDE 84

A Taste of Typelevel

— Part 3 —

slide-85
SLIDE 85

Date Metric Mon Low Tue High

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

slide-86
SLIDE 86

Date Mon Low Tue High

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

slide-87
SLIDE 87

How can we prevent that error happening again?

slide-88
SLIDE 88

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

slide-89
SLIDE 89

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

import shapeless._ import syntax.sized._

slide-90
SLIDE 90

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

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

slide-92
SLIDE 92

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

slide-93
SLIDE 93

How?

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

slide-94
SLIDE 94

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

slide-95
SLIDE 95

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

slide-96
SLIDE 96

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

slide-97
SLIDE 97

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

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

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

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

Merging Fields

slide-102
SLIDE 102

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

slide-103
SLIDE 103

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

slide-104
SLIDE 104

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

slide-105
SLIDE 105

val user = User(
 123L, 
 “Bruce Wayne”,
 Some(“bruce@example.org”)) val update = Update( 
 Some(“Batman”), 
 None)

How do we get to…

User(
 123L, 
 “Batman”, 
 Some(“bruce@example.org”))

slide-106
SLIDE 106

Bulletin

https://github.com/davegurnell/bulletin

slide-107
SLIDE 107

How?

User

String Option[String] … Option[String] Option[
 Option[String] ] …

Update

slide-108
SLIDE 108

How?

User

String Option[String] … Option[String] Option[
 Option[String] ] …

Update

Head

slide-109
SLIDE 109

How?

User

String Option[String] … Option[String] Option[
 Option[String] ] …

Update

Head The Rest…

slide-110
SLIDE 110

How?

Type constraints Implicit methods HLists Labelled generic Macros …

slide-111
SLIDE 111

val user = User(
 123L, 
 "Bruce Wayne”,
 Some(“bruce@example.org”)) val update = Update( 
 Some(“Batman”), 
 None) import bulletin._ val updated = user.merge(update) // User(
 // 123L, 
 // “Batman”, 
 // Some(“bruce@example.org”))

slide-112
SLIDE 112

val user = User(
 123L, 
 "Bruce Wayne”,
 Some(“bruce@example.org”)) val update = Update( 
 Some(“Batman”), 
 None) import bulletin._ val updated = user.merge(update) // User(
 // 123L, 
 // “Batman”, 
 // Some(“bruce@example.org”))

slide-113
SLIDE 113

Summary

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

slide-114
SLIDE 114

Using Power Tools

Can go one of two ways…

slide-115
SLIDE 115

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

Simple Types Power Share

slide-117
SLIDE 117

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

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

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

Thanks!

Richard Dallaway, @d6y

underscore.io

slide-121
SLIDE 121

Thanks!

Richard Dallaway, @d6y

underscore.io

Amanda Laucher Wesley Reisz Noel Welsh Dave Gurnell Miles Sabin Jono Ferguson Julio Capote Alessandro Zoffoli