340

# Simplicity in composition September 18, 2017

## Transcript

Chang (@adelbertchang) Simplicity in composition Scala World 2017 1 / 67
2. ### Composition A: type (set) of values Adelbert Chang (@adelbertchang) Simplicity

in composition Scala World 2017 2 / 67
3. ### Composition A: type (set) of values ⊕: A × A

→ A Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 2 / 67
4. ### Composition A: type (set) of values ⊕: A × A

→ A 1A : identity for ⊕ Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 2 / 67
5. ### Composition A: type (set) of values ⊕: A × A

→ A 1A : identity for ⊕ (x ⊕ y) ⊕ z = x ⊕ (y ⊕ z) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 2 / 67
6. ### Composition A: type (set) of values ⊕: A × A

→ A 1A : identity for ⊕ (x ⊕ y) ⊕ z = x ⊕ (y ⊕ z) x = x ⊕ 1A = 1A ⊕ x Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 2 / 67
7. ### (Z, +, 0) Adelbert Chang (@adelbertchang) Simplicity in composition Scala

World 2017 3 / 67
8. ### ([a], + +, []) Adelbert Chang (@adelbertchang) Simplicity in composition

Scala World 2017 4 / 67
9. ### (A → A, ◦, a → a) Adelbert Chang (@adelbertchang)

Simplicity in composition Scala World 2017 5 / 67
10. ### trait Monoid[A] { def combine(x: A, y: A): A def

empty: A } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 6 / 67
11. ### 1 2 3 4 5 6 7 8 Adelbert Chang

(@adelbertchang) Simplicity in composition Scala World 2017 7 / 67
12. ### 3 3 4 5 6 7 8 Adelbert Chang (@adelbertchang)

Simplicity in composition Scala World 2017 8 / 67
13. ### 6 4 5 6 7 8 Adelbert Chang (@adelbertchang) Simplicity

in composition Scala World 2017 9 / 67
14. ### 15 6 7 8 Adelbert Chang (@adelbertchang) Simplicity in composition

Scala World 2017 10 / 67

11 / 67
16. ### 1 2 3 4 5 6 7 8 Adelbert Chang

(@adelbertchang) Simplicity in composition Scala World 2017 12 / 67
17. ### 3 7 11 15 Adelbert Chang (@adelbertchang) Simplicity in composition

Scala World 2017 13 / 67

2017 14 / 67

15 / 67
20. ### 1 2 3 4 5 6 7 8 3 7

11 15 10 26 36 Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 16 / 67
21. ### Associative composition allows for modular decomposition and reasoning. Adelbert Chang

(@adelbertchang) Simplicity in composition Scala World 2017 17 / 67
22. ### Composing programs A Adelbert Chang (@adelbertchang) Simplicity in composition Scala

World 2017 18 / 67
23. ### Composing programs F[A] Adelbert Chang (@adelbertchang) Simplicity in composition Scala

World 2017 19 / 67
24. ### Composing programs (F[A], F[A]) => F[A] Adelbert Chang (@adelbertchang) Simplicity

in composition Scala World 2017 20 / 67
25. ### Composing programs (F[A], F[B]) => F[?] Adelbert Chang (@adelbertchang) Simplicity

in composition Scala World 2017 21 / 67
26. ### Composing programs (F[A], F[B]) => F[(A, B)] Adelbert Chang (@adelbertchang)

Simplicity in composition Scala World 2017 22 / 67
27. ### Composing programs F( ): type of program Adelbert Chang (@adelbertchang)

Simplicity in composition Scala World 2017 23 / 67
28. ### Composing programs F( ): type of program ⊗ : F(A)

× F(B) → F((A, B)) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 23 / 67
29. ### Composing programs F( ): type of program ⊗ : F(A)

× F(B) → F((A, B)) η : A → F(A) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 23 / 67
30. ### Composing programs F( ): type of program ⊗ : F(A)

× F(B) → F((A, B)) η : A → F(A) (fa ⊗ fb) ⊗ fc ∼ = fa ⊗ (fb ⊗ fc) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 23 / 67
31. ### Composing programs F( ): type of program ⊗ : F(A)

× F(B) → F((A, B)) η : A → F(A) (fa ⊗ fb) ⊗ fc ∼ = fa ⊗ (fb ⊗ fc) fa ∼ = fa ⊗ ηUnit ∼ = ηUnit ⊗ fa Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 23 / 67
32. ### Composing programs def zipOption[A, B] (oa: Option[A], ob: Option[B]): Option[(A,

B)] = (oa, ob) match { case (Some(a), Some(b)) => Some((a, b)) case _ => None } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 24 / 67
33. ### Composing programs def zipOption[A, B] (oa: Option[A], ob: Option[B]): Option[(A,

B)] = (oa, ob) match { case (Some(a), Some(b)) => Some((a, b)) case _ => None } def pureOption[A](a: A): Option[A] = Some(a) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 24 / 67
34. ### Composing programs def zipList[A, B] (la: List[A], lb: List[B]): List[(A,

B)] = la match { case Nil => Nil case h :: t => lb.map((h, _)) ++ zipList(t, lb) } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 25 / 67
35. ### Composing programs def zipList[A, B] (la: List[A], lb: List[B]): List[(A,

B)] = la match { case Nil => Nil case h :: t => lb.map((h, _)) ++ zipList(t, lb) } def pureList[A](a: A): List[A] = List(a) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 25 / 67
36. ### Composing programs def zipFunction[A, B, X] (f: X => A,

g: X => B): X => (A, B) = (x: X) => (f(x), g(x)) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 26 / 67
37. ### Composing programs def zipFunction[A, B, X] (f: X => A,

g: X => B): X => (A, B) = (x: X) => (f(x), g(x)) def pureFunction[A, X](a: A): X => A = (_: X) => a Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 26 / 67
38. ### /** Same as Applicative */ trait Monoidal[F[_]] { def zip[A,

B](fa: F[A], fb: F[B]): F[(A, B)] def pure[A](a: A): F[A] /* def map[A, B](fa: F[A])(f: A => B): F[B] */ } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 27 / 67
39. ### User input Password reqs Features Latest posts Sign-up form Featured

Welcome page Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 28 / 67
40. ### Composing programs (F[A], F[B]) => F[(A, B)] Adelbert Chang (@adelbertchang)

Simplicity in composition Scala World 2017 29 / 67
41. ### Composing independent programs (F[A], F[B]) => F[(A, B)] Adelbert Chang

(@adelbertchang) Simplicity in composition Scala World 2017 30 / 67
42. ### Composing programs F[A] Adelbert Chang (@adelbertchang) Simplicity in composition Scala

World 2017 31 / 67
43. ### Composing dependent programs (F[A], A => F[B]) => F[B] Adelbert

Chang (@adelbertchang) Simplicity in composition Scala World 2017 32 / 67
44. ### Composing dependent programs F( ): type of program 1> =

>: (A → F(B) × B → F(C)) → A → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 33 / 67
45. ### Composing dependent programs F( ): type of program > >=:

(F(A) × A → F(B)) → F(B) 1> = >: (A → F(B) × B → F(C)) → A → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 33 / 67
46. ### Composing dependent programs F( ): type of program > >=:

(F(A) × A → F(B)) → F(B) η : A → F(A) 1> = >: (A → F(B) × B → F(C)) → A → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 33 / 67
47. ### Composing dependent programs F( ): type of program > >=:

(F(A) × A → F(B)) → F(B) η : A → F(A) (fa > >= f ) > >= g = fa > >= (f >=> g)1 1> = >: (A → F(B) × B → F(C)) → A → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 33 / 67
48. ### Composing dependent programs F( ): type of program > >=:

(F(A) × A → F(B)) → F(B) η : A → F(A) (fa > >= f ) > >= g = fa > >= (f >=> g)1 f (x) = η(x) > >= f 1> = >: (A → F(B) × B → F(C)) → A → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 33 / 67
49. ### Composing dependent programs F( ): type of program > >=:

(F(A) × A → F(B)) → F(B) η : A → F(A) (fa > >= f ) > >= g = fa > >= (f >=> g)1 f (x) = η(x) > >= f fa = fa > >= η 1> = >: (A → F(B) × B → F(C)) → A → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 33 / 67
50. ### Composing dependent programs def flatMapOption[A, B] (oa: Option[A], f: A

=> Option[B]): Option[B] = oa match { case Some(a) => f(a) case None => None } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 34 / 67
51. ### Composing dependent programs def flatMapList[A, B] (la: List[A], f: A

=> List[B]): List[B] = la match { case Nil => Nil case h :: t => f(h) ++ flatMapList(t, f) } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 35 / 67
52. ### Composing dependent programs def flatMapFunction[A, B, X] (fa: X =>

A, f: A => (X => B)): X => B = (x: X) => f(fa(x))(x) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 36 / 67
53. ### trait Monad[F[_]] { def flatMap[A, B](fa: F[A])(f: A => F[B]):

F[B] def pure[A](a: A): F[A] } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 37 / 67
54. ### trait Monad[F[_]] extends Monoidal[F] { def flatMap[A, B](fa: F[A])(f: A

=> F[B]): F[B] def pure[A](a: A): F[A] } Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 38 / 67
55. ### A nicer monad (fa > >= f ) > >=

g = fa > >= (f >=> g) f (x) = η(x) > >= f fa = fa > >= η Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 39 / 67
56. ### A nicer monad f : A → F(B) g :

B → F(C) h : C → F(D) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 40 / 67
57. ### A nicer monad f : A → F(B) g :

B → F(C) h : C → F(D) (f >=> g) >=> h = f >=> (g >=> h) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 40 / 67
58. ### A nicer monad f : A → F(B) g :

B → F(C) h : C → F(D) (f >=> g) >=> h = f >=> (g >=> h) f = f >=> η = η >=> f Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 40 / 67
59. ### User info Friends Cookies Logs Proﬁle Recommendations News feed Adelbert

Chang (@adelbertchang) Simplicity in composition Scala World 2017 41 / 67
60. ### Category theory studies the algebra of composition. Adelbert Chang (@adelbertchang)

Simplicity in composition Scala World 2017 42 / 67
61. ### Category theory objects: A, B, C ... Adelbert Chang (@adelbertchang)

Simplicity in composition Scala World 2017 43 / 67
62. ### Category theory objects: A, B, C ... arrows: f :

A → B, g : B → C ... Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 43 / 67
63. ### Category theory objects: A, B, C ... arrows: f :

A → B, g : B → C ... 1A : A → A Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 43 / 67
64. ### Category theory objects: A, B, C ... arrows: f :

A → B, g : B → C ... 1A : A → A (f ◦ g) ◦ h = f ◦ (g ◦ h) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 43 / 67
65. ### Category theory objects: A, B, C ... arrows: f :

A → B, g : B → C ... 1A : A → A (f ◦ g) ◦ h = f ◦ (g ◦ h) f = f ◦ 1A = 1A ◦ f Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 43 / 67
66. ### Category theory B A C g 1B f g◦f 1A

1C Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 44 / 67
67. ### Category theory B A C g 1B f g◦f 1A

1C Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 44 / 67
68. ### Category theory B A C g 1B f g◦f 1A

1C Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 44 / 67
69. ### Category theory: monoids • x y x⊕y 1A Adelbert Chang

(@adelbertchang) Simplicity in composition Scala World 2017 45 / 67
70. ### Category theory: monoids • x y x⊕y 1A Adelbert Chang

(@adelbertchang) Simplicity in composition Scala World 2017 45 / 67
71. ### Category theory: monoids • x y x⊕y 1A Adelbert Chang

(@adelbertchang) Simplicity in composition Scala World 2017 45 / 67
72. ### Category theory: monoids • x y x⊕y 1A Adelbert Chang

(@adelbertchang) Simplicity in composition Scala World 2017 45 / 67

World 2017 46 / 67
74. ### Category theory: monads F(B) A F(C) f ?◦f Adelbert Chang

(@adelbertchang) Simplicity in composition Scala World 2017 46 / 67
75. ### Category theory: monads F(B) A F(C) f ?◦f > >=:

(F(B) × B → F(C)) → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 46 / 67
76. ### Category theory: monads F(B) A F(C) f ?◦f > >=:

(B → F(C)) → F(B) → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 47 / 67
77. ### Category theory: monads F(B) A F(C) g∗ f g∗◦f >

>=: (B → F(C)) → F(B) → F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 48 / 67
78. ### Category theory: monads B A C g 1B B→F(B) f

g ◦f 1A A→F(A) 1C C→F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 49 / 67
79. ### Category theory: monads B A C g 1B B→F(B) f

g ◦f 1A A→F(A) 1C C→F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 49 / 67
80. ### Category theory: monads B A C g 1B B→F(B) f

g ◦f 1A A→F(A) 1C C→F(C) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 49 / 67
81. ### Category theory: monads B A C g 1B B→F(B) f

g ◦f 1A A→F(A) 1C C→F(C) η : X → F(X) Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 49 / 67
82. ### User info Friends Cookies Logs Proﬁle Recommendations News feed Adelbert

Chang (@adelbertchang) Simplicity in composition Scala World 2017 50 / 67
83. ### What if we have diﬀerent monoids, monads, etc? Adelbert Chang

(@adelbertchang) Simplicity in composition Scala World 2017 51 / 67
84. ### (Monoid[A], Monoid[B]) => Monoid[?] Adelbert Chang (@adelbertchang) Simplicity in composition

Scala World 2017 52 / 67
85. ### Product composition: monoids (Monoid[A], Monoid[B]) => Monoid[(A, B)] Adelbert Chang

(@adelbertchang) Simplicity in composition Scala World 2017 53 / 67
86. ### Product composition: monoids def combine(x: (A, B), y: (A, B)):

(A, B) = { val a = x._1 combine y._1 val b = x._2 combine y._2 (a, b) } 0Assuming Monoid[A] and Monoid[B] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 54 / 67
87. ### Product composition: monoids def combine(x: (A, B), y: (A, B)):

(A, B) = { val a = x._1 combine y._1 val b = x._2 combine y._2 (a, b) } def empty: (A, B) = (empty[A], empty[B]) 0Assuming Monoid[A] and Monoid[B] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 54 / 67
88. ### (Monoidal[F], Monoidal[G]) => Monoidal[?] Adelbert Chang (@adelbertchang) Simplicity in composition

Scala World 2017 55 / 67
89. ### Product composition: lax monoidal functors type L[X] = (F[X], G[X])

(Monoidal[F], Monoidal[G]) => Monoidal[L] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 56 / 67
90. ### Product composition: lax monoidal functors def zip[A, B](x: (F[A], G[A]),

y: (F[B], G[B])): (F[(A, B)], G[(A, B)]) = { val f = x._1 zip y._1 val g = x._2 zip y._2 (f, g) } 0Assuming Monoidal[F] and Monoidal[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 57 / 67
91. ### Product composition: lax monoidal functors def zip[A, B](x: (F[A], G[A]),

y: (F[B], G[B])): (F[(A, B)], G[(A, B)]) = { val f = x._1 zip y._1 val g = x._2 zip y._2 (f, g) } def pure[A](a: A): (F[A], G[A]) = (a.pure[F], a.pure[G]) 0Assuming Monoidal[F] and Monoidal[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 57 / 67

93. ### Product composition: monads def flatMap[A, B] (xa: (F[A], G[A]))(ff: A

=> (F[B], G[B])): (F[(A, B)], G[(A, B)]) = { val f = xa._1.flatMap(a => ff(a)._1) val g = xa._2.flatMap(a => ff(a)._2) (f, g) } 0Assuming Monad[F] and Monad[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 59 / 67
94. ### Nested composition: lax monoidal functors type L[X] = F[G[X]] (Monoidal[F],

Monoidal[G]) => Monoidal[L] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 60 / 67
95. ### User input Password reqs Features Latest posts Sign-up form Featured

Welcome page Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 61 / 67
96. ### Nested composition: lax monoidal functors def zip[A, B](fga: F[G[A]], fgb:

F[G[B]]): F[G[(A, B)]] = { val fp: F[(G[A], G[B])] = fga zip fgb fp.map { case (ga, gb) => ga zip gb } } 0Assuming Monoidal[F] and Monoidal[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 62 / 67
97. ### Nested composition: lax monoidal functors def zip[A, B](fga: F[G[A]], fgb:

F[G[B]]): F[G[(A, B)]] = { val fp: F[(G[A], G[B])] = fga zip fgb fp.map { case (ga, gb) => ga zip gb } } def pure[A](a: A): F[G[A]] = a.pure[G].pure[F] 0Assuming Monoidal[F] and Monoidal[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 62 / 67

101. ### Nested composition: monads def flatMap[A, B](fga: F[G[A]](f: A => F[G[B]]):

F[G[B]] = fga.flatMap { (ga: G[A]) => ??? } 0Assuming Monad[F] and Monad[G] Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 65 / 67
102. ### Review Associative composition allows for modular decomposition and reasoning Adelbert

Chang (@adelbertchang) Simplicity in composition Scala World 2017 66 / 67
103. ### Review Associative composition allows for modular decomposition and reasoning Monoids

compose A’s, lax monoidal/applicative functors compose independent programs, monads compose dependent programs Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 66 / 67
104. ### Review Associative composition allows for modular decomposition and reasoning Monoids

compose A’s, lax monoidal/applicative functors compose independent programs, monads compose dependent programs Category theory studies composition, and each of the above can be framed as a category Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 66 / 67
105. ### Review Associative composition allows for modular decomposition and reasoning Monoids

compose A’s, lax monoidal/applicative functors compose independent programs, monads compose dependent programs Category theory studies composition, and each of the above can be framed as a category Monoids compose Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 66 / 67
106. ### Review Associative composition allows for modular decomposition and reasoning Monoids

compose A’s, lax monoidal/applicative functors compose independent programs, monads compose dependent programs Category theory studies composition, and each of the above can be framed as a category Monoids compose Lax monoidal/applicative functors compose Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 66 / 67
107. ### Review Associative composition allows for modular decomposition and reasoning Monoids

compose A’s, lax monoidal/applicative functors compose independent programs, monads compose dependent programs Category theory studies composition, and each of the above can be framed as a category Monoids compose Lax monoidal/applicative functors compose Monads in general do not compose See: monad transformers, extensible (algebraic) eﬀects Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 66 / 67
108. ### References Equational reasoning at scale - Gabriel Gonzalez http://www.haskellforall.com/2014/07/ equational-reasoning-at-scale.html

Invariant Shadows - Michael Pilquist http://mpilquist.github.io/blog/2015/06/22/ invariant-shadows-part-2/ All About Applicative - Me! https://www.youtube.com/watch?v=Mn7BtPALFys A categorial view of computational eﬀects - Emily Riehl https://www.youtube.com/watch?v=6t6bsWVOIzs Conceptual Mathematics - F. William Lawvere and Stephen H. Schanuel Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 67 / 67