-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.html
537 lines (432 loc) · 20.1 KB
/
index.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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Implicits Inspected and Explained</title>
<meta name="description" content="Presentation for ScalaDays 2016">
<meta name="author" content="Tim Soethout">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
<link rel="stylesheet" href="css/reveal.css">
<link rel="stylesheet" href="css/theme/ing.css" id="theme">
<!-- Code syntax highlighting -->
<link rel="stylesheet" href="lib/css/tomorrow.css">
<!-- diagrams -->
<link rel="stylesheet" href="css/mermaid.css">
<script src="lib/js/mermaid.min.js"></script>
<!-- TOC -->
<!-- <link rel="stylesheet" href="plugin/presentable/presentable.min.css"> -->
<!-- Printing and PDF exports -->
<script>
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
</script>
<!--[if lt IE 9]>
<script src="lib/js/html5shiv.js"></script>
<![endif]-->
<!-- some hacking to make it readable -->
<style>
.reveal section img {
border: none;
box-shadow: none;
}
.reveal .diagram-data {
display: none;
}
</style>
</head>
<body>
<div class="reveal">
<!-- Any section element inside of this container is displayed as a slide -->
<div class="slides" >
<section data-markdown>
<script type="text/template">
# Implicits Inspected and Explained
ScalaDays 2016 Berlin
<!-- At the keynote at Scala Exchange Jessica Kerr mentioned that there is very much documentation for starting and expert Scala developers, but (almost) nothing in between. In this talk I want to demystify implicits.
Implicits are a fairly advanced feature and a very important aspect of the Scala language. They help with writing concise code and enable lots of DSLs. On the other side they can be very magical for an untrained eye. In this talk we will delve into idiomatic use cases of implicits and how the Scala compiler resolves them. If time allows we will jump into type classes as well. -->
Tim Soethout - ING Bank
http://blog.timmybankers.nl
Outline: Introduction - Implicits - Resolving - Type Classes - Wrap up <!-- .element: class="fragment" data-fragment-index="1" -->
Note:
- Welcome!
- Many Scala users see implicits everywhere, but their exact use remains a bit magic
- Goal of talk is to give you an intuition on how implicits work and where to look when things go haywire.
- Target audience is Scala developers, who already know the language and syntax
- We already heard a lot about implicits. Martin emphasised the importance of implicits for the Scala Language in the keynore. Yesterday a lot of the talks in the advanced track used and abused implicits a lot.
- Outline: Context, Implicits, Scoping, Typeclasses
</script>
</section>
<section>
<section data-markdown>
<script type="text/template">
### About myself
Tim Soethout
- Functional programmer at heart
- Scala/FP evangelist/trainer inside ING Bank
![ING](image/ING_logo.png) <!-- .element: style="width:10em;" -->
- PhD Candidate
<!-- ![ING](image/CWI.png) <!-/- .element: style="width:10em;" -/-> -->
Note:
- Bachelor CKI, Master Computing Science in Utrecht - Lot's of Haskell
- Now Scala
@ ING:
- Popularising Functional Programming
+ Scale out
+ Scala => JVM
- Lightbend/Typesafe certified trainer: Scala & Akka
- 3 courses
@ CWI: Research institute in the Netherlands for Math and Computer Science
Mention about ING:
- Internal training each month, Scala in upcoming
- If you want to know more, please come talk to me
</script>
</section>
<!-- <section data-markdown> -->
<!-- <script type="text/template">
### Scala @ ![ING](image/ING_logo.png) .element: style="width:4em; margin: 0;" -->
<!-- - Trainings each month (~10 new Scala/Akka devs)
- Enthusiastic Scala Guild
- ~4 full Scala applications in Production (Retail banking NL)
- Internal reusable library on Scala and Finagle (embedded in lots of applications)
- More and more departments starting, also for data science
Note:
- ING
+ 52k employees worldwide, 40 countries
+ NL 150+ DevOps teams
- Monthly meetups
- Sponsors of ScalaDays Amsterdam (2015) and Berlin (2016)
- RAF, Coral, Calendar, Elements
- Also used in non-dutch departments
</script> -->
<!-- </section> -->
</section>
<section>
<section data-markdown>
## Implicits
</section>
<section data-markdown>
### What?
- Use values without explicit reference
- OO: _is a_ + _has a_
- Implicits add: _is viewable as a_
- Loose Coupling, Tight Cohesion
Note:
- _is a_: extends: Cow is an Animal
- _has a_: members: Animal has a name
- Cow is viewable as a coat hanger
- Enables: Small core interfaces + rich views
Implicits enable you to use values without explicitly referencing them. This enables you to write less code, and let implicits do the heavy lifting for you. We will see how this can be useful.
If we look at Object Orientation, traditionally we see _is a_ and _has a_, respectively 'a Cow _is an_ Animal' and 'an Animal has a name' as field for example. Implicits enable _is viewable as a_ on top of this. This means we can convert values to other more rich values implicitly. 'a Cow _is viewable as a_ coat hanger'.This enables small and clean core interfaces and rich views on top of this, resulting in Loose Coupling, but Tight Cohesion.
</section>
<section data-markdown>
### Examples
- Akka
```scala
trait ScalaActorRef
def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit = ...
}```
```scala
actorRef ! SomeMessage("text")
```
- Futures
```scala
object Future {
def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T] = ...
}```
```scala
Future {
doExpensiveComputation()
}
```
Note:
- implicit to pass in sender from actor context
- `ExectutionContext` to handle the thread management
Let's look at some examples.
In Akka when sending a message the tell (bang) is implemented with an implicit parameter `sender`. This enables us to send message to other actors without having to pass in itself in as the sender explicitly.
Another example is the implicit `ExecutionContext` when using `Future`s. `ExecutionContext` takes care of all the handing of the threads used by Futures under the hood. The implicit allows you to select a runtime for this once and use it implicitly for all the applicable `Future`s. The interface also allows you pass in another thread handling mechanism explicitly.
</section>
<section data-markdown>
### Examples (2)
- Collections
```scala
trait TraversableOnce[+A] {
def sum[B >: A](implicit num: Numeric[B]): B = ...
}```
```scala
List(1,2,3).sum
res0: Int = 6
```
Note:
- `Numeric` type class to allow sum on things that can be added
It is also used in the Scala collections library. For example you can use `sum` on any `TraversableOnce` if there is an implicit available which makes sure we can do `plus` on the elements of the collection. This is an example of a type class.
</section>
<section data-markdown>
### Examples (3)
- Finagle
```scala
@implicitNotFound("Builder is not fully configured: Cluster: ${HasCluster}, Codec: ${HasCodec},
HostConnectionLimit: ${HasHostConnectionLimit}")
private[builder] trait ClientConfigEvidence[HasCluster, HasCodec, HasHostConnectionLimit]
class ClientBuilder[Req, Rep, HasCluster, HasCodec, HasHostConnectionLimit] private[finagle](...) {
def build()(
implicit THE_BUILDER_IS_NOT_FULLY_SPECIFIED_SEE_ClientBuilder_DOCUMENTATION:
ClientConfigEvidence[HasCluster, HasCodec, HasHostConnectionLimit]
): Service[Req, Rep] = ...
}```
```scala
val builder: ClientBuilder[Request, Response, Yes, Yes, Nothing] =
ClientBuilder()
.codec(Http())
.hosts("twitter.com:80")
builder.build()
```
```
Error:(24, 15) Builder is not fully configured: Cluster: com.twitter.finagle.builder.ClientConfig.Yes,
Codec: com.twitter.finagle.builder.ClientConfig.Yes, HostConnectionLimit: Nothing
builder.build()
^```
Note:
- Builder only allows build() when all the configuration has been done
- `@implicitNotFound` custom error message when Implicit was not found.
This example is a bit more involved. Finagle provides a type safe builder class, which only builds if all the required settings are configured. The `build()` method can only be called when an implicit value is available which proofs that all settings are configured. If we construct a partially configured builder and try to `build()` it, we will get a compile time error. The annotation `@implicitNotFound` provides us with a custom error message when the implicit can not be found.
</section>
<section data-markdown>
### Implicits enable
- DSLs
- Type evidence
- Reduce verbosity
- Type classes
- Dependency Injection at Compile time
- Extending libraries
Note:
- Some examples, but there is more
- DSLs: reuse standard Scala types and collections by extending them with your library functions
- Type evidence can help with creating more type safe interfaces, i.e. in Builders, constraint evidence
- Pass in dependencies depending on which implicit is in scope, used in Play & Slick
- Less writing, more implicit
I hope these examples have convinced you of the power of implicits. Implicits allow for a lot more. They can be used to extend types, including all the types in the standard library, allowing for powerful DSLs to be created embedded in the language.
They can provide type evidence as we saw in the Finagle builder and also in the `TraversableOnce.sum` example where a `Numeric[B]` had to be available.
They allow us to write less by leaving ceremony out, and thus reduce verbosity.
Implits enable us to create type classes in Scala, which add features for generic programming and extending of libraries.
We can do dependency injection by having different implicits in scope and this is all resolved at compile time.
And we can extend libraries or code that is out of our control.
</section>
<section data-markdown>
### But beware
- Resolution rules can be difficult
- Automatic conversions
- Do not overuse
Note:
- Powerful, but can be magical in grasping, IDE support is really handy here
- Simple lexical examination not always enough
- Be careful with conversions, implicits can help, also when being explicit
+ Semantics can be different (`List` to `Stream` or `Double` to `Int`)
- If you do find yourself using implicits, always ask yourself if there is a way to achieve the same thing without their help. Principle of least power - Li Haoyi - which Martin referenced in the keynote
But take care. Implicits are a powerful extensions but being less explicit can become more magical. It is not always clear which method or field is being called just by looking at the code. Fortunately IDE's can help here.
Also, if values can be converted to values of other types, this can be triggered without you as developer even noticing and can result in doing to much work or possibly worse, automatic translations between types with different semantics, a List to a Stream for example.
If you can achieve your goal without implicits do not use them.
</section>
<section data-markdown>
### Demo
- Implicit conversions (a.k.a. Implicit views)
```scala
implicit def a2B(a : A) : B = ...```
- Implicit parameters
```scala
def method(implicit x : Int) = ...```
- Implicit classes
```scala
implicit class X(y: Int)```
- Implicit declarations
```scala
implicit val x = ...```
Note:
- Explain how REPLesent works (`r` and `n`)
- `ImplicitParameter.sc`
- `ImplicitConversion.sc`
- `ImplicitClass.sc`
- Explain about IDE support
</section>
<section data-markdown>
### Scoping
#### Odersky Explains
Lookup precedence:
1. By name only, without any prefix
2. In "implicit scope":
- companion/package object of
+ the source type
+ its parameters + supertype and supertraits
Note:
1. Visible as locals/members of enclosing classes and packages or as imports
2. companion objects that bear some relation to the type
- the importance is to be as general as possible without reverting to whole program analysis like Haskell does).
- This is so that library developers can provide sensible defaults in Companion Objects and Package Objects and users can override those by importing or defining implicits in local scope
</section>
<section data-markdown>
### Demo
+ Scoping and resolving
Note:
- First show `scoping` package
- `Scoping.sc`
</section>
<!-- <section data-markdown>
### Outline
- Manifestations of Implicits
+ Implicit conversions -> implicit views
+ Implicit parameters (http://www.lihaoyi.com/post/StrategicScalaStylePrincipleofLeastPower.html#implicit-method-parameter)
+ Implicit val/var/defs
+ Implicit (value) class
- Use cases + how it works underneath
+ javap
+ use intellij to see whats where
* command + shift + p - see what is used for implicit conversion
* control + q - see what implicits are in scope for this value
+ show implicits from predef in scope
- Well known uses?
+ `implicitly`
+ Akka ActorRef
+ ExecutionContext (futures)
+ Dependency Injection
+ Type classes
+ Circe + Spray JSON etc
+ Shapeless
- Scalacheck - Arbitrary?
- Utilities and tooling support (think of a better name)
- Type classes
- Ending
Note:
- http://www.cakesolutions.net/teamblogs/demystifying-implicits-and-typeclasses-in-scala
- http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html
- http://stackoverflow.com/questions/5598085/where-does-scala-look-for-implicits - goede voorbeelden
- https://vimeo.com/20308847
- http://eed3si9n.com/revisiting-implicits-without-import-tax
+ http://eed3si9n.com/implicit-parameter-precedence-again
- Scala In Depth, the book
</section> -->
</section>
<section>
<section data-markdown>
## Typeclasses
</section>
<section data-markdown>
### Typeclass uses
- Ad-hoc polymorphism
- Extension of libraries
```
trait Numeric[T] extends Ordering[T] {
def plus(x: T, y: T): T
def minus(x: T, y: T): T
def times(x: T, y: T): T
...
}
```
Note:
- Term originates from Haskell, because no subtyping, to allow overloading of functions and operators
- Extending library without changing library code, loose coupling
+ Examples: Comparability, printability, summing
+ Type class captures common sets of operations
- Example sort a collection if elements of collection are comparable
+ Can be done by inheritance, interface etc
+ But, static and only when writing the element type
+ Basically extend the library
- Can be implemented in Scala using implicits
</section>
<section data-markdown>
### Demo
Typeclass for JSON Serialisation
- Naive with subtyping
- Typeclass + improvements
Note:
- Adding JSonSerialisable everywhere will clutter your implemetation => High Coupling
- `typeclass/Naive.sc`
- `typeclass/JsonSerializer.sc`
</section>
</section>
<section>
<section data-markdown>
## Wrap up
</section>
<section data-markdown>
<script type="text/template">
### Recap
- Implicits are powerful
- Be careful with conversions
- Implicit precedence: first look local, then in companion/package object
- Typeclasses to extend libraries
### Questions? <!-- .element: class="fragment" data-fragment-index="2" -->
Note:
- Powerful. Allow to write expressive code.
- Use cases range from DSLs to extending libraries to full blown DI.
- Use your IDE to help spot conversions and see which implicits are used
- Typeclasses, extend in Nonintrusive way, enabling loose coupling
- Don't forget next slides on code
</script>
</section>
</section>
<section data-markdown>
## Implicits Inspected and Explained
Tim Soethout @ ScalaDays 2016 Berlin
http://blog.timmybankers.nl
### References
[Slides](http://blog.timmybankers.nl/implicits-inspected-and-explained-slides)
/
[Code](https://github.com/TimSoethout/implicits-inspected-and-explained-slides/tree/gh-pages/code)
- Scala documentation:
+ [Java Converters](http://docs.scala-lang.org/overviews/collections/conversions-between-java-and-scala-collections.html)
+ [Finding Implicits](http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html)
- Book: [Scala In Depth](https://www.manning.com/books/scala-in-depth)
- [Effective Scala](http://twitter.github.io/effectivescala/)
- Blog [All Things Runnable](http://lalitpant.blogspot.nl/2008/08/scala-implicits-dose-of-magic-part-1.html)
- [Scala Gitter channel](https://gitter.im/scala/scala), special thanks to @Ichoran and @som-snytt
- [REPLesent](https://github.com/marconilanna/REPLesent), for the demo slides
</section>
</div>
</div>
<script src="lib/js/head.min.js"></script>
<script src="js/reveal.js"></script>
<script>
// Full list of configuration options available at:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
slideNumber: true,
width: 1440,
height: 900,
// width: 1366,
// height: 767,
margin: 0,
transition: 'convex', // none/fade/slide/convex/concave/zoom
// Optional reveal.js plugins
dependencies: [
{ src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
// { src: 'plugin/highlight/highlight.js', async: true, condition: function() { return !!document.querySelector( 'pre code' ); }, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: 'plugin/zoom-js/zoom.js', async: true },
{ src: 'plugin/notes/notes.js', async: true },
{ src: 'plugin/mermaid/mermaid.js' }
// { src: 'plugin/presentable/presentable.min.js', callback: function() { presentable.toc({
// framework: "revealjs",
// // Untitled slides are excluded from TOC
// hideNoTitle: true,
// titles: "h2,.presentable-title",
// });}}
]
});
</script>
<!-- <script>
(function(){
document.querySelector('.footer span').innerHTML = (document.querySelector('title').innerHTML);
})();
</script> -->
</body>
</html>