Slide 1

Slide 1 text

Why I Like Functional Programming Adelbert Chang Machine Learning @ Box, Inc.

Slide 2

Slide 2 text

Let’s go back.. http://gauss.cs.ucsb.edu/home/images/UCSB-from-air.jpg

Slide 3

Slide 3 text

2011

Slide 4

Slide 4 text

2011 void insert(Node* &tree, int value) { if (!tree) return; Node *trav = tree, *parent; while (trav) { parent = trav; if (value < trav->data) trav = trav->left; else if (value > trav->data) trav = trav->right; else break; } if (value < parent->data) parent->left = new Node(value); else parent->right = new Node(value); }

Slide 5

Slide 5 text

Physics and Math

Slide 6

Slide 6 text

Physics and Math •Simplicity and consistency across problems

Slide 7

Slide 7 text

Physics and Math •Simplicity and consistency across problems •Example: Deriving laws of motion from first principles

Slide 8

Slide 8 text

Physics and Math •Simplicity and consistency across problems •Example: Deriving laws of motion from first principles •vf = v0 + a Δt

Slide 9

Slide 9 text

Physics and Math •Simplicity and consistency across problems •Example: Deriving laws of motion from first principles •vf = v0 + a Δt •vavg = v0 + ½aΔt

Slide 10

Slide 10 text

Physics and Math •Simplicity and consistency across problems •Example: Deriving laws of motion from first principles •vf = v0 + a Δt •vavg = v0 + ½aΔt •x = x0 + v0t + ½at2

Slide 11

Slide 11 text

Deriving x = x0 + v0t + ½at2 Physics and Math

Slide 12

Slide 12 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Physics and Math

Slide 13

Slide 13 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt Physics and Math

Slide 14

Slide 14 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt (x - x0) = vavg * Δt Physics and Math

Slide 15

Slide 15 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt (x - x0) = vavg * Δt x = x0 + (vavg * Δt) Physics and Math

Slide 16

Slide 16 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt (x - x0) = vavg * Δt x = x0 + (vavg * Δt) vavg = ½(vf + v0) Physics and Math

Slide 17

Slide 17 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt (x - x0) = vavg * Δt x = x0 + (vavg * Δt) vavg = ½(vf + v0) a = Δv / Δt Physics and Math

Slide 18

Slide 18 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt (x - x0) = vavg * Δt x = x0 + (vavg * Δt) vavg = ½(vf + v0) a = Δv / Δt a = (vf - v0) / Δt Physics and Math

Slide 19

Slide 19 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt (x - x0) = vavg * Δt x = x0 + (vavg * Δt) vavg = ½(vf + v0) a = Δv / Δt a = (vf - v0) / Δt vf - v0 = a Δt Physics and Math

Slide 20

Slide 20 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt (x - x0) = vavg * Δt x = x0 + (vavg * Δt) vavg = ½(vf + v0) a = Δv / Δt a = (vf - v0) / Δt vf - v0 = a Δt vf = v0 + a Δt Physics and Math

Slide 21

Slide 21 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt (x - x0) = vavg * Δt x = x0 + (vavg * Δt) ½(v0 + aΔt + v0) vavg = ½(vf + v0) a = Δv / Δt a = (vf - v0) / Δt vf - v0 = a Δt vf = v0 + a Δt Physics and Math

Slide 22

Slide 22 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt (x - x0) = vavg * Δt x = x0 + (vavg * Δt) ½(v0 + aΔt + v0) ½(2v0 + a Δt) vavg = ½(vf + v0) a = Δv / Δt a = (vf - v0) / Δt vf - v0 = a Δt vf = v0 + a Δt Physics and Math

Slide 23

Slide 23 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt (x - x0) = vavg * Δt x = x0 + (vavg * Δt) ½(v0 + aΔt + v0) ½(2v0 + a Δt) vavg = v0 + ½aΔt vavg = ½(vf + v0) a = Δv / Δt a = (vf - v0) / Δt vf - v0 = a Δt vf = v0 + a Δt Physics and Math

Slide 24

Slide 24 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt (x - x0) = vavg * Δt x = x0 + (vavg * Δt) x = x0 + ((v0 + ½aΔt) * Δt) ½(v0 + aΔt + v0) ½(2v0 + a Δt) vavg = v0 + ½aΔt vavg = ½(vf + v0) a = Δv / Δt a = (vf - v0) / Δt vf - v0 = a Δt vf = v0 + a Δt Physics and Math

Slide 25

Slide 25 text

Deriving x = x0 + v0t + ½at2 vavg = Δx/Δt Δx = vavg * Δt (x - x0) = vavg * Δt x = x0 + (vavg * Δt) x = x0 + ((v0 + ½aΔt) * Δt) x0 + v0t + ½at2 ½(v0 + aΔt + v0) ½(2v0 + a Δt) vavg = v0 + ½aΔt vavg = ½(vf + v0) a = Δv / Δt a = (vf - v0) / Δt vf - v0 = a Δt vf = v0 + a Δt Physics and Math

Slide 26

Slide 26 text

2012

Slide 27

Slide 27 text

2012 sealed abstract class Tree case class Branch(data: Int, left: Tree, right: Tree) extends Tree case class Leaf() extends Tree def insert(tree: Tree, value: Int): Tree = tree match { case Leaf() => Branch(value, Leaf(), Leaf()) case b@Branch(d, l, r) => if (value < d) Branch(d, insert(l, value), r) else if (value > d) Branch(d, l, insert(r, value) else b }

Slide 28

Slide 28 text

Hmm.. functional programming seems pretty cool.

Slide 29

Slide 29 text

But is it as cool as physics and math? Hmm.. functional programming seems pretty cool.

Slide 30

Slide 30 text

Functional Programming

Slide 31

Slide 31 text

Functional Programming programming with functions

Slide 32

Slide 32 text

programming with pure functions Functional Programming

Slide 33

Slide 33 text

programming with pure functions Functional Programming

Slide 34

Slide 34 text

Functions

Slide 35

Slide 35 text

def parseIntPartial(s: String): Int = s.toInt // can throw NumberFormatException Functions

Slide 36

Slide 36 text

def parseIntPartial(s: String): Int = s.toInt // can throw NumberFormatException Functions def parseIntTotal(s: String): Option[Int] = try { Some(s.toInt) } catch { case nfe: NumberFormatException => None }

Slide 37

Slide 37 text

Functions

Slide 38

Slide 38 text

class Rng(var seed: Long) { def nextInt(): Int = { val int = getInt(seed) mutate(seed) int } } Functions

Slide 39

Slide 39 text

class Rng(var seed: Long) { def nextInt(): Int = { val int = getInt(seed) mutate(seed) int } } case class Rng(seed: Long) { def nextInt: (Rng, Int) = { val int = getInt(seed) val newSeed = f(seed) (Rng(newSeed), int) } } Functions

Slide 40

Slide 40 text

Referential Transparency * Taken from Higher Order blog post "What Purity Is and Isn't" May 29, 2015 http://blog.higher-order.com/blog/2012/09/13/what-purity-is-and-isnt/

Slide 41

Slide 41 text

Referential Transparency An expression e is referentially transparent if * Taken from Higher Order blog post "What Purity Is and Isn't" May 29, 2015 http://blog.higher-order.com/blog/2012/09/13/what-purity-is-and-isnt/

Slide 42

Slide 42 text

Referential Transparency An expression e is referentially transparent if for all programs p * Taken from Higher Order blog post "What Purity Is and Isn't" May 29, 2015 http://blog.higher-order.com/blog/2012/09/13/what-purity-is-and-isnt/

Slide 43

Slide 43 text

Referential Transparency An expression e is referentially transparent if for all programs p every occurrence of e in p * Taken from Higher Order blog post "What Purity Is and Isn't" May 29, 2015 http://blog.higher-order.com/blog/2012/09/13/what-purity-is-and-isnt/

Slide 44

Slide 44 text

Referential Transparency An expression e is referentially transparent if for all programs p every occurrence of e in p can be replaced with the result of evaluating e * Taken from Higher Order blog post "What Purity Is and Isn't" May 29, 2015 http://blog.higher-order.com/blog/2012/09/13/what-purity-is-and-isnt/

Slide 45

Slide 45 text

Referential Transparency An expression e is referentially transparent if for all programs p every occurrence of e in p can be replaced with the result of evaluating e without changing the result of evaluating p.* * Taken from Higher Order blog post "What Purity Is and Isn't" May 29, 2015 http://blog.higher-order.com/blog/2012/09/13/what-purity-is-and-isnt/

Slide 46

Slide 46 text

Referential Transparency

Slide 47

Slide 47 text

x4 - 12x2 + 36 = 0 Referential Transparency

Slide 48

Slide 48 text

x4 - 12x2 + 36 = 0 y = x2 Referential Transparency

Slide 49

Slide 49 text

x4 - 12x2 + 36 = 0 y = x2 y2 - 12y + 36 = 0 Referential Transparency

Slide 50

Slide 50 text

x4 - 12x2 + 36 = 0 y = x2 y2 - 12y + 36 = 0 ax2 + bx + c = 0 Referential Transparency

Slide 51

Slide 51 text

x4 - 12x2 + 36 = 0 y = x2 y2 - 12y + 36 = 0 ax2 + bx + c = 0 (-b ± √ b2 - 4ac) / 2a Referential Transparency

Slide 52

Slide 52 text

x4 - 12x2 + 36 = 0 y = x2 y2 - 12y + 36 = 0 ax2 + bx + c = 0 (-b ± √ b2 - 4ac) / 2a a = 1 b = -12 c = 36 Referential Transparency

Slide 53

Slide 53 text

x4 - 12x2 + 36 = 0 y = x2 y2 - 12y + 36 = 0 ax2 + bx + c = 0 (-b ± √ b2 - 4ac) / 2a a = 1 b = -12 c = 36 (-(-12) ± √ (-12)2 - 4(1)(36)) / 2(1) Referential Transparency

Slide 54

Slide 54 text

x4 - 12x2 + 36 = 0 y = x2 y2 - 12y + 36 = 0 ax2 + bx + c = 0 (-b ± √ b2 - 4ac) / 2a a = 1 b = -12 c = 36 (-(-12) ± √ (-12)2 - 4(1)(36)) / 2(1) 12 / 2 Referential Transparency

Slide 55

Slide 55 text

x4 - 12x2 + 36 = 0 y = x2 y2 - 12y + 36 = 0 ax2 + bx + c = 0 (-b ± √ b2 - 4ac) / 2a a = 1 b = -12 c = 36 (-(-12) ± √ (-12)2 - 4(1)(36)) / 2(1) 12 / 2 y = 6 Referential Transparency

Slide 56

Slide 56 text

x4 - 12x2 + 36 = 0 y = x2 y2 - 12y + 36 = 0 ax2 + bx + c = 0 (-b ± √ b2 - 4ac) / 2a a = 1 b = -12 c = 36 (-(-12) ± √ (-12)2 - 4(1)(36)) / 2(1) 12 / 2 y = 6 x2 = 6 Referential Transparency

Slide 57

Slide 57 text

x4 - 12x2 + 36 = 0 y = x2 y2 - 12y + 36 = 0 ax2 + bx + c = 0 (-b ± √ b2 - 4ac) / 2a a = 1 b = -12 c = 36 (-(-12) ± √ (-12)2 - 4(1)(36)) / 2(1) 12 / 2 y = 6 x2 = 6 x = ± √ 6 Referential Transparency

Slide 58

Slide 58 text

Referential Transparency

Slide 59

Slide 59 text

def userInfo(id: UserId): Future[UserData] val userId = . . . val fetchData = userInfo(userId) fetchData.retry { case StatusCode(429) => fetchData } Referential Transparency

Slide 60

Slide 60 text

def userInfo(id: UserId): Future[UserData] val userId = . . . val fetchData = userInfo(userId) fetchData.retry { case StatusCode(429) => fetchData } Referential Transparency

Slide 61

Slide 61 text

def userInfo(id: UserId): Future[UserData] val userId = . . . val fetchData = userInfo(userId) fetchData.retry { case StatusCode(429) => userInfo(userId) } Referential Transparency

Slide 62

Slide 62 text

def userInfo(id: UserId): Future[UserData] val userId = . . . val fetchData = userInfo(userId) fetchData.retry { case StatusCode(429) => userInfo(userId) } ??? Referential Transparency

Slide 63

Slide 63 text

def userInfo(id: UserId): Task[UserData] val userId = . . . val fetchData = userInfo(userId) fetchData.retry { case StatusCode(429) => fetchData } Referential Transparency

Slide 64

Slide 64 text

trait Task[A] { def unsafeRun(): A } def userInfo(id: UserId): Task[UserData] val userId = . . . val fetchData = userInfo(userId) fetchData.retry { case StatusCode(429) => fetchData } Referential Transparency

Slide 65

Slide 65 text

Functions

Slide 66

Slide 66 text

bar: B => C baz: C => D foo: A => B Functions

Slide 67

Slide 67 text

baz.compose(bar).compose(foo): A => D bar: B => C baz: C => D foo: A => B Functions

Slide 68

Slide 68 text

Tracking Effects

Slide 69

Slide 69 text

Tracking Effects •Interesting programs will have effects •Optional values, error handling, asynchronous computation, input/output •Usual means aren’t quite nice

Slide 70

Slide 70 text

Tracking Effects •Interesting programs will have effects •Optional values, error handling, asynchronous computation, input/output •Usual means aren’t quite nice Solution:

Slide 71

Slide 71 text

Tracking Effects •Interesting programs will have effects •Optional values, error handling, asynchronous computation, input/output •Usual means aren’t quite nice Solution: Reify effects as values.

Slide 72

Slide 72 text

Missing values

Slide 73

Slide 73 text

// A value that might exist is either.. sealed abstract class Option[A] // ..there final case class Some[A](a: A) extends Option[A] // .. or not there final case class None[A]() extends Option[A] Missing values

Slide 74

Slide 74 text

def lookup(map: Map[Foo, Bar], foo: Foo): Option[Bar] = if (map.contains(foo)) Some(map(foo)) else None Missing values

Slide 75

Slide 75 text

Errors sealed abstract class Either[+E, +A] final case class Success[+A](a: A) extends Either[Nothing, A] final case class Failure[+E](e: E) extends Either[E, Nothing]

Slide 76

Slide 76 text

sealed abstract class Error final case object UserDoesNotExist extends Error final case object InvalidToken extends Error def userInfo(uid: UserId, tk: Token): Either[Error, UserInfo] = . . . Errors

Slide 77

Slide 77 text

Manipulating Effects

Slide 78

Slide 78 text

Manipulating Effects •The type signature of our functions reflect the effects involved

Slide 79

Slide 79 text

Manipulating Effects •The type signature of our functions reflect the effects involved def tokenFor(uid: UserId): Option[EncryptedToken] def decrypt(token: EncryptedToken): Token /** Client side */ val encrypted: Option[EncryptedToken] = tokenFor(. . .) // Want EncryptedToken, have Option[EncryptedToken] val decrypted = decrypt(???)

Slide 80

Slide 80 text

/** Apply a pure function to an effectful value */ trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] } Manipulating Effects

Slide 81

Slide 81 text

/** Apply a pure function to an effectful value */ trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] } Manipulating Effects new Functor[Option] { def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa match { case Some(a) => Some(f(a)) case None() => None() } }

Slide 82

Slide 82 text

def tokenFor(uid: UserId): Option[EncryptedToken] def decrypt(token: EncryptedToken): Token /** Client side */ val encrypted: Option[EncryptedToken] = tokenFor(. . .) val decrypted = encrypted.map(tk => decrypt(tk)) Manipulating Effects

Slide 83

Slide 83 text

•Similar mechanisms for manipulating multiple effects def tokenFor(uid: UserId): Option[EncryptedToken] def decrypt(token: EncryptedToken): Token /** Client side */ val encrypted: Option[EncryptedToken] = tokenFor(. . .) val decrypted = encrypted.map(tk => decrypt(tk)) Manipulating Effects

Slide 84

Slide 84 text

Lens

Slide 85

Slide 85 text

Lens •Often want getters/setters when working with data

Slide 86

Slide 86 text

Lens •Often want getters/setters when working with data •If getters/setters are per-object, cannot compose

Slide 87

Slide 87 text

Lens •Often want getters/setters when working with data •If getters/setters are per-object, cannot compose •As with effects, reify as data •Getter: get an A field in an object S •Setter: change an A field in an object S

Slide 88

Slide 88 text

Lens •Often want getters/setters when working with data •If getters/setters are per-object, cannot compose •As with effects, reify as data •Getter: get an A field in an object S •Setter: change an A field in an object S trait Lens[S, A] { def get(s: S): A def set(s: S, a: A): S }

Slide 89

Slide 89 text

trait Lens[S, A] { outer => def get(s: S): A def set(s: S, a: A): S def modify(s: S, f: A => A): S = set(s, f(get(s))) def compose[B](other: Lens[A, B]): Lens[S, B] = new Lens[S, B] { def get(s: S): B = other.get(get(s)) def set(s: S, b: B): S = set(s, other.set(outer.get(s), b)) } } Lens

Slide 90

Slide 90 text

case class Employee(position: Position) object Employee { val position: Lens[Employee, Position] = . . . } case class Team(manager: Employee, . . .) object Team { val manager: Lens[Team, Employee] = . . . } Lens

Slide 91

Slide 91 text

case class Employee(position: Position) object Employee { val position: Lens[Employee, Position] = . . . } case class Team(manager: Employee, . . .) object Team { val manager: Lens[Team, Employee] = . . . } /** Client side */ val l: Lens[Team, Position] = Team.manager.compose(Employee.position) l.set(someTeam, somePosition) Lens

Slide 92

Slide 92 text

Lens

Slide 93

Slide 93 text

•Effect-ful modifications can be useful •Possibly failing: A => Option[A] •Many possible values: A => List[A] •Async: A => Task[A] Lens

Slide 94

Slide 94 text

•Effect-ful modifications can be useful •Possibly failing: A => Option[A] •Many possible values: A => List[A] •Async: A => Task[A] trait Lens[S, A] { def modifyOption(s: S, f: A => Option[A]): Option[S] def modifyList(s: S, f: A => List[A]): List[S] def modifyTask(s: S, f: A => Task[A]): Task[S] } Lens

Slide 95

Slide 95 text

trait Lens[S, A] { def modifyOption(s: S, f: A => Option[A]): Option[S] = f(get(s)).map(a => set(s, a)) def modifyList(s: S, f: A => List[A]): List[S] = f(get(s)).map(a => set(s, a)) def modifyTask(s: S, f: A => Task[A]): Task[S] = f(get(s)).map(a => set(s, a)) } Lens

Slide 96

Slide 96 text

trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] = f(get(s)).map(a => set(s, a)) } Lens

Slide 97

Slide 97 text

trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] = f(get(s)).map(a => set(s, a)) } •Example functors: Lens

Slide 98

Slide 98 text

trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] = f(get(s)).map(a => set(s, a)) } •Example functors: •Option, Either, Future, List, IO Lens

Slide 99

Slide 99 text

trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] = f(get(s)).map(a => set(s, a)) } •Example functors: •Option, Either, Future, List, IO •What if we want to just modify without any effect? Lens

Slide 100

Slide 100 text

trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] = f(get(s)).map(a => set(s, a)) } •Example functors: •Option, Either, Future, List, IO •What if we want to just modify without any effect? •We want the F[A] to just be a plain A Lens

Slide 101

Slide 101 text

trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] = f(get(s)).map(a => set(s, a)) } •Example functors: •Option, Either, Future, List, IO •What if we want to just modify without any effect? •We want the F[A] to just be a plain A •Type-level identity function Lens

Slide 102

Slide 102 text

trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] = f(get(s)).map(a => set(s, a)) } •Example functors: •Option, Either, Future, List, IO •What if we want to just modify without any effect? •We want the F[A] to just be a plain A •Type-level identity function Lens def identity[A](a: A): A = a

Slide 103

Slide 103 text

Id type Id[A] = A

Slide 104

Slide 104 text

Id type Id[A] = A new Functor[Id] { def map[A, B](fa: Id[A])(f: A => B): Id[B] = }

Slide 105

Slide 105 text

Id type Id[A] = A new Functor[Id] { def map[A, B](fa: Id[A])(f: A => B): Id[B] = }

Slide 106

Slide 106 text

type Id[A] = A new Functor[Id] { def map[A, B](fa: A)(f: A => B): B = } Id

Slide 107

Slide 107 text

type Id[A] = A new Functor[Id] { def map[A, B](fa: A)(f: A => B): B = f(fa) } Id

Slide 108

Slide 108 text

trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] = f(get(s)).map(a => set(s, a)) def modify(s: S, f: A => A): S = modifyF[Id](s, f) } Id

Slide 109

Slide 109 text

Setting trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] = f(get(s)).map(a => set(s, a)) def modify(s: S, f: A => A): S = modifyF[Id](s, f) def set(s: S, a: A): S = modify(s, const(a)) }

Slide 110

Slide 110 text

Setting trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] = f(get(s)).map(a => set(s, a)) def modify(s: S, f: A => A): S = modifyF[Id](s, f) def set(s: S, a: A): S = modify(s, const(a)) } def const[A, B](a: A)(b: B): A = a

Slide 111

Slide 111 text

Setting trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] = f(get(s)).map(a => set(s, a)) def modify(s: S, f: A => A): S = modifyF[Id](s, f) def set(s: S, a: A): S = modify(s, const(a)) } def const[A, B](a: A)(b: B): A = a

Slide 112

Slide 112 text

trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] def get(s: S): A def modify(s: S, f: A => A): S = modifyF[Id](s, f) def set(s: S, a: A): S = modify(s, const(a)) } def const[A, B](a: A)(b: B): A = a Setting

Slide 113

Slide 113 text

Getting trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] def get(s: S): A }

Slide 114

Slide 114 text

Getting trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] def get(s: S): A } •Can we define `get` in terms of `modify`?

Slide 115

Slide 115 text

Getting trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] def get(s: S): A } •Can we define `get` in terms of `modify`? •`modifyF` gives us some F[S].. but we want an A

Slide 116

Slide 116 text

Getting trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] def get(s: S): A } •Can we define `get` in terms of `modify`? •`modifyF` gives us some F[S].. but we want an A •We need some way of "ignoring" the S parameter and still get an A back

Slide 117

Slide 117 text

Getting trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] def get(s: S): A } •Can we define `get` in terms of `modify`? •`modifyF` gives us some F[S].. but we want an A •We need some way of "ignoring" the S parameter and still get an A back •Type-level constant function

Slide 118

Slide 118 text

Getting trait Lens[S, A] { def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] def get(s: S): A } •Can we define `get` in terms of `modify`? •`modifyF` gives us some F[S].. but we want an A •We need some way of "ignoring" the S parameter and still get an A back •Type-level constant function def const[A, B](a: A)(b: B): A = a

Slide 119

Slide 119 text

Getting * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 120

Slide 120 text

type Const[Z, A] = Z Getting * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 121

Slide 121 text

type Const[Z, A] = Z new Functor[Const[Z, ?]] { // * def map[A, B](fa: Const[Z, A])(f: A => B): Const[Z, B] } Getting * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 122

Slide 122 text

type Const[Z, A] = Z new Functor[Const[Z, ?]] { // * def map[A, B](fa: Const[Z, A])(f: A => B): Const[Z, B] } Getting * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 123

Slide 123 text

new Functor[Const[Z, ?]] { // * def map[A, B](fa: Z)(f: A => B): Z = } type Const[Z, A] = Z Getting * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 124

Slide 124 text

new Functor[Const[Z, ?]] { // * def map[A, B](fa: Z)(f: A => B): Z = fa } type Const[Z, A] = Z Getting * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 125

Slide 125 text

trait Lens[S, Z] { def modifyF[F[_] : Functor](s: S, f: Z => F[Z]): F[S] def get(s: S): Z = { val const: Const[Z, S] = modifyF[Const[Z, ?]](s, z => z) // * const } } new Functor[Const[Z, ?]] { // * def map[A, B](fa: Z)(f: A => B): Z = fa } type Const[Z, A] = Z Getting * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 126

Slide 126 text

trait Lens[S, A] { /** Abstract */ def modifyF[F[_] : Functor](s: S, f: A => F[A]): F[S] /** Implemented */ def modify(s: S, f: A => A): S def get(s: S): A def set(s: S, a: A): S def compose[B](other: Lens[A, B]): Lens[S, B] } Lens

Slide 127

Slide 127 text

Are Id and Const just party tricks?

Slide 128

Slide 128 text

Traverse trait Traverse[F[_]] { def traverse[G[_] : Applicative, A, B] (fa: F[A])(f: A => G[B]): G[F[B]] }

Slide 129

Slide 129 text

Traverse trait Traverse[F[_]] { def traverse[G[_] : Applicative, A, B] (fa: F[A])(f: A => G[B]): G[F[B]] } def validate[A] (data: List[A])(f: A => Option[B]): Option[List[B]]

Slide 130

Slide 130 text

Traverse trait Traverse[F[_]] { def traverse[G[_] : Applicative, A, B] (fa: F[A])(f: A => G[B]): G[F[B]] } def scatterGather[A] (data: List[A])(f: A => Task[B]): Task[List[B]] def validate[A] (data: List[A])(f: A => Option[B]): Option[List[B]]

Slide 131

Slide 131 text

Traverse * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 132

Slide 132 text

traverse: F[A] => (A => G[B]) => G[F[B]] Traverse * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 133

Slide 133 text

traverse: F[A] => (A => G[B]) => G[F[B]] traverse[Id, A, B] Traverse * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 134

Slide 134 text

traverse: F[A] => (A => G[B]) => G[F[B]] traverse[Id, A, B] F[A] => (A => Id[B]) => Id[F[B]] Traverse * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 135

Slide 135 text

traverse: F[A] => (A => G[B]) => G[F[B]] traverse[Id, A, B] F[A] => (A => Id[B]) => Id[F[B]] F[A] => (A => B) => F[B] Traverse * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 136

Slide 136 text

traverse: F[A] => (A => G[B]) => G[F[B]] traverse[Id, A, B] F[A] => (A => Id[B]) => Id[F[B]] F[A] => (A => B) => F[B] Traverse * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 137

Slide 137 text

traverse: F[A] => (A => G[B]) => G[F[B]] traverse[Id, A, B] F[A] => (A => Id[B]) => Id[F[B]] F[A] => (A => B) => F[B] traverse[Const[Z, ?], A, B] // *, If Z can be "reduced" Traverse * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 138

Slide 138 text

traverse: F[A] => (A => G[B]) => G[F[B]] traverse[Id, A, B] F[A] => (A => Id[B]) => Id[F[B]] F[A] => (A => B) => F[B] traverse[Const[Z, ?], A, B] // *, If Z can be "reduced" F[A] => (A => Const[Z, B]) => Const[Z, F[B]] Traverse * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 139

Slide 139 text

traverse: F[A] => (A => G[B]) => G[F[B]] traverse[Id, A, B] F[A] => (A => Id[B]) => Id[F[B]] F[A] => (A => B) => F[B] traverse[Const[Z, ?], A, B] // *, If Z can be "reduced" F[A] => (A => Const[Z, B]) => Const[Z, F[B]] F[A] => (A => Z) => Z Traverse * Const[Z, ?] syntax is valid due to kind-projector plugin https://github.com/non/kind-projector

Slide 140

Slide 140 text

Interested?

Slide 141

Slide 141 text

Interested? •Functional Programming •Cats, Scalaz •Argonaut, Atto, Monocle, Shapeless

Slide 142

Slide 142 text

Interested? •Functional Programming •Cats, Scalaz •Argonaut, Atto, Monocle, Shapeless •Algebra •Algebird, Algebra, Breeze, Spire

Slide 143

Slide 143 text

Interested? •Functional Programming •Cats, Scalaz •Argonaut, Atto, Monocle, Shapeless •Algebra •Algebird, Algebra, Breeze, Spire •Big Data •Scalding, Scoobi, Spark

Slide 144

Slide 144 text

Interested? •Functional Programming •Cats, Scalaz •Argonaut, Atto, Monocle, Shapeless •Algebra •Algebird, Algebra, Breeze, Spire •Big Data •Scalding, Scoobi, Spark •Systems •Doobie, HTTP4S, Remotely, Scalaz-stream

Slide 145

Slide 145 text

EOF