September 18, 2017
360

# Simplicity in composition

September 18, 2017

## Transcript

1. Simplicity in composition
Scala World 2017
Adelbert 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

15. 36
Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 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

18. 10 26
Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 14 / 67

19. 36
Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 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

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

(fa >
>= f ) >
>= g = fa >
>= (f >=> g)
f (x) = η(x) >
>= f
fa = fa >
>= η
Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 39 / 67

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

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

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

Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 46 / 67

F(B)
A F(C)
f
?◦f
Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 46 / 67

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

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

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

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

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

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

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

type L[X] = (F[X], G[X])
Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 58 / 67

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)
}
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

type L[X] = F[G[X]]
Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 63 / 67

type L[X] = F[G[X]]
Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 64 / 67

def flatMap[A, B](fga: F[G[A]](f: A => F[G[B]]): F[G[B]] =
Adelbert Chang (@adelbertchang) Simplicity in composition Scala World 2017 65 / 67

def flatMap[A, B](fga: F[G[A]](f: A => F[G[B]]): F[G[B]] =
fga.flatMap { (ga: G[A]) =>
???
}
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