-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathslides.html
215 lines (156 loc) · 4.48 KB
/
slides.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
<!DOCTYPE html>
<html>
<head>
<title>Introduction to Type Classes in Scala</title>
<meta charset="utf-8">
<style>
@import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz);
@import url(https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic);
@import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700,400italic);
body { font-family: 'Droid Serif'; }
h1, h2, h3 {
font-family: 'Yanone Kaffeesatz';
font-weight: normal;
}
.remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
.ref {
line-height: 0;
position: relative;
vertical-align: baseline;
top: -0.4em;
left: -0.3em;
font-size: 0.8em;
}
.footnote {
position: absolute;
bottom: 5em;
font-size: 0.8em;
}
</style>
</head>
<body>
<textarea id="source">
class: center, middle
# Introduction to Type Classes in Scala
by [Brad Fritz](http://bfritz.com/)
---
## Goals
* What is a [type class](http://typelevel.org/cats/typeclasses.html)?
* Why should I care?
* How can I write a Scala type class?
* Introduce a couple well-known type classes:
* [Semigroup](http://typelevel.org/cats/typeclasses/semigroup.html)
* [Monoid](http://typelevel.org/cats/typeclasses/monoid.html)
But:
* Avoid jargon from category theory or functional programming.
* Do not assume advanced Scala experience.
---
## What
Technique to apply a common pattern over multiple types. Roughly:
trait + implicit values ≈ duck typing
-- -- --
Pretty printing example:
```scala
scala> println(123.pp)
int 123
scala> println("123".pp)
str 123
scala> println(Person("John", "Doe").pp)
name: Doe, John
scala> println(Some("thing").pp)
got it
scala> println(None.pp)
dunno
```
---
## What
Another example .ref[*]:
```scala
def sumInts(list: List[Int]): Int = list.foldRight(0)(_ + _)
def concatStrings(list: List[String]): String = list.foldRight("")(_ ++ _)
def unionSets[A](list: List[Set[A]]): Set[A] = list.foldRight(Set.empty[A])(_ union _)
```
They all have the same shape. Can we write a more generic version?
```scala
def combineAll[A](list: List[A], ???): A =
list.foldRight(???)(???)
```
.footnote[\* From http://typelevel.org/cats/typeclasses.html]
---
## What
```scala
trait T[A] {
def empty: A
def combine(x: A, y: A): A
}
// Algebra and FP nerds have a name for this shape: a monoid*
def combineAll[A](list: List[A], A: T[A]): A = list.foldRight(A.empty)(A.combine)
```
.footnote[\* ...assuming `empty()` and `combine()` satisify some laws.]
---
## Why
Extract common patterns, like `combineAll()`, into library code...
* often with typical implementations provided, and
* without losing the ability to customize behavior for specific types.
???
http4s `Managed` / `Releaseable` use case:
https://gist.github.com/rossabaker/718772d6a17918a2b515d26ee6236d8e
---
## How - Pretty Printing Demo
Example inspired by Łukasz Indykiewicz's blog post at:
http://blog.scalac.io/2017/04/19/typeclasses-in-scala.html
---
## Common FP Type Classes
* Semigroup
* Monoid
* Eq
* Monad
* Functor
* Applicative
* [many others](https://github.com/typelevel/cats/issues/1633)
---
## Semigroup
```scala
trait Semigroup[A] {
def combine(x: A, y: A): A
}
```
Laws:
* `combine()` is associative
http://typelevel.org/cats/typeclasses/semigroup.html
---
## Monoid
```scala
trait Monoid[A] {
def combine(x: A, y: A): A
def empty: A
}
```
Or:
```scala
trait Monoid[A] extends Semigroup[A] {
def empty: A
}
```
Laws:
* `combine()` is associative
* `empty()` is identity for `combine()`
http://typelevel.org/cats/typeclasses/monoid.html
---
## Credit and Further Reading:
* Łukasz Indykiewicz<br/>http://blog.scalac.io/2017/04/19/typeclasses-in-scala.html
* Cody Allen<br/>https://github.com/ceedubs/intro-to-cats
* Cats project<br/>http://typelevel.org/cats/
* Ross Baker<br/>https://gist.github.com/rossabaker/718772d6a17918a2b515d26ee6236d8e
* Daniel Westheide<br/>http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html
* Daniel Shin<br/>http://www.danishin.com/article/Semigroup_And_Monoid_In_Scala
* Scala Exercises<br/>https://www.scala-exercises.org/cats/
* Typeclassopedia<br/>https://wiki.haskell.org/Typeclassopedia
</textarea>
<script src="https://remarkjs.com/downloads/remark-latest.min.js">
</script>
<script>
var slideshow = remark.create();
</script>
</body>
</html>