-
Notifications
You must be signed in to change notification settings - Fork 1
/
implicits.html
589 lines (482 loc) · 61.8 KB
/
implicits.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
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
<!DOCTYPE html>
<html lang="en" prefix="og: http://ogp.me/ns# fb: https://www.facebook.com/2008/fbml">
<head>
<title>Implicits - Stackdiver as a Service</title>
<!-- Using the latest rendering mode for IE -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="canonical" href="https://www.lyh.me/implicits.html">
<meta name="author" content="Neville Li" />
<meta name="keywords" content="scala,fp" />
<meta name="description" content="In this post we’re going to take a closer look at Scala implicits and various use cases. Basics Let’s first look at the basics. There’re 3 main basic uses of implicits, as an argument, as a conversion method, and enhancing an existing class, a.k.a. the “Pimp My Library” pattern. Implicit arguments Suppose we have a basic function like this. def plus(x: Int) = x + 1 plus(10) // => 11 We can add a second argument and make it a curried function. def plus(x: Int)(y: Int) = x + y plus(10)(1) // => 11 We can then make the second argument implicit and supply it via an implicit val. def plus(x: Int)(implicit y: Int) = x + y implicit val one = 1 plus(10) // => 11 Since plus needs an implicit argument of type Int and there happens to be one in the scope, one is applied automatically. However it won’t work if there are multiple implicit vals. implicit val one = 1 implicit val two = 2 plus(10) // => ambiguous implicit values This example isn’t very interesting and one can usually use argument with a default value instead. However implicit arguments are handy for decoupling behavior …" />
<meta property="og:site_name" content="Stackdiver as a Service" />
<meta property="og:type" content="article"/>
<meta property="og:title" content="Implicits"/>
<meta property="og:url" content="https://www.lyh.me/implicits.html"/>
<meta property="og:description" content="In this post we’re going to take a closer look at Scala implicits and various use cases. Basics Let’s first look at the basics. There’re 3 main basic uses of implicits, as an argument, as a conversion method, and enhancing an existing class, a.k.a. the “Pimp My Library” pattern. Implicit arguments Suppose we have a basic function like this. def plus(x: Int) = x + 1 plus(10) // => 11 We can add a second argument and make it a curried function. def plus(x: Int)(y: Int) = x + y plus(10)(1) // => 11 We can then make the second argument implicit and supply it via an implicit val. def plus(x: Int)(implicit y: Int) = x + y implicit val one = 1 plus(10) // => 11 Since plus needs an implicit argument of type Int and there happens to be one in the scope, one is applied automatically. However it won’t work if there are multiple implicit vals. implicit val one = 1 implicit val two = 2 plus(10) // => ambiguous implicit values This example isn’t very interesting and one can usually use argument with a default value instead. However implicit arguments are handy for decoupling behavior …"/>
<meta property="article:published_time" content="2017-04-21" />
<meta property="article:section" content="code" />
<meta property="article:tag" content="scala" />
<meta property="article:tag" content="fp" />
<meta property="article:author" content="Neville Li" />
<!-- Bootstrap -->
<link rel="stylesheet" href="https://www.lyh.me/theme/css/bootstrap.min.css" type="text/css"/>
<link href="https://www.lyh.me/theme/css/font-awesome.min.css" rel="stylesheet">
<link href="https://www.lyh.me/theme/css/pygments/monokai.css" rel="stylesheet">
<link href="https://www.lyh.me/theme/css/typogrify.css" rel="stylesheet">
<link rel="stylesheet" href="https://www.lyh.me/theme/css/style.css" type="text/css"/>
<link href="https://www.lyh.me/feeds/all.atom.xml" type="application/atom+xml" rel="alternate"
title="Stackdiver as a Service ATOM Feed"/>
<link href="https://www.lyh.me/feeds/code.atom.xml" type="application/atom+xml" rel="alternate"
title="Stackdiver as a Service code ATOM Feed"/>
</head>
<body>
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="https://www.lyh.me/" class="navbar-brand">
Stackdiver as a Service </a>
</div>
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav">
<li><a href="https://www.lyh.me/pages/about-me.html">
About Me
</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
</div> <!-- /.navbar -->
<!-- Banner -->
<!-- End Banner -->
<!-- Content Container -->
<div class="container">
<div class="row">
<div class="col-sm-9">
<section id="content">
<article>
<header class="page-header">
<h1>
<a href="https://www.lyh.me/implicits.html"
rel="bookmark"
title="Permalink to Implicits">
Implicits
</a>
</h1>
</header>
<div class="entry-content">
<div class="panel">
<div class="panel-body">
<footer class="post-info">
<span class="label label-default">Date</span>
<span class="published">
<i class="fa fa-calendar"></i><time datetime="2017-04-21T08:48:00-04:00"> Fri 21 April 2017</time>
</span>
<span class="label label-default">Category</span>
<a href="https://www.lyh.me/category/code.html">code</a>
<span class="label label-default">Tags</span>
<a href="https://www.lyh.me/tag/scala.html">scala</a>
/
<a href="https://www.lyh.me/tag/fp.html">fp</a>
</footer><!-- /.post-info --> </div>
</div>
<p>In this post we’re going to take a closer look at Scala implicits and various use cases.</p>
<h2>Basics</h2>
<p>Let’s first look at the basics. There’re 3 main basic uses of implicits, as an argument, as a conversion method, and enhancing an existing class, a.k.a. the “Pimp My Library” pattern.</p>
<h3>Implicit arguments</h3>
<p>Suppose we have a basic function like this.</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Int</span><span class="o">)</span> <span class="k">=</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">plus</span><span class="o">(</span><span class="mi">10</span><span class="o">)</span> <span class="c1">// => 11</span>
</code></pre></div>
<p>We can add a second argument and make it a curried function.</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Int</span><span class="o">)(</span><span class="n">y</span><span class="k">:</span> <span class="kt">Int</span><span class="o">)</span> <span class="k">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="n">plus</span><span class="o">(</span><span class="mi">10</span><span class="o">)(</span><span class="mi">1</span><span class="o">)</span> <span class="c1">// => 11</span>
</code></pre></div>
<p>We can then make the second argument implicit and supply it via an <code>implicit val</code>.</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Int</span><span class="o">)(</span><span class="k">implicit</span> <span class="n">y</span><span class="k">:</span> <span class="kt">Int</span><span class="o">)</span> <span class="k">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="k">implicit</span> <span class="k">val</span> <span class="n">one</span> <span class="k">=</span> <span class="mi">1</span>
<span class="n">plus</span><span class="o">(</span><span class="mi">10</span><span class="o">)</span> <span class="c1">// => 11</span>
</code></pre></div>
<p>Since <code>plus</code> needs an implicit argument of type <code>Int</code> and there happens to be one in the scope, <code>one</code> is applied automatically. However it won’t work if there are multiple <code>implicit val</code>s.</p>
<div class="highlight"><pre><span></span><code><span class="k">implicit</span> <span class="k">val</span> <span class="n">one</span> <span class="k">=</span> <span class="mi">1</span>
<span class="k">implicit</span> <span class="k">val</span> <span class="n">two</span> <span class="k">=</span> <span class="mi">2</span>
<span class="n">plus</span><span class="o">(</span><span class="mi">10</span><span class="o">)</span> <span class="c1">// => ambiguous implicit values</span>
</code></pre></div>
<p>This example isn’t very interesting and one can usually use argument with a default value instead. However implicit arguments are handy for decoupling behavior from business logic. Let’s take a look at <code>Future[+T]</code> for example.</p>
<div class="highlight"><pre><span></span><code><span class="k">val</span> <span class="n">f</span> <span class="k">=</span> <span class="nc">Future</span> <span class="o">{</span>
<span class="nc">Thread</span><span class="o">.</span><span class="n">sleep</span><span class="o">(</span><span class="mi">1000</span><span class="o">)</span> <span class="c1">// simulating slow computation</span>
<span class="mi">42</span>
<span class="o">}</span>
<span class="c1">// => Cannot find an implicit ExecutionContext.</span>
</code></pre></div>
<p>A closer look at the <span class="caps">API</span> shows that <code>Future { code }</code> is actually an <code>apply</code> method on the companion object. The implicit argument <code>executor</code> determines the concurrency behavior, e.g. fixed, fork-join or other thread pools.</p>
<div class="highlight"><pre><span></span><code><span class="k">object</span> <span class="nc">Future</span> <span class="o">{</span>
<span class="k">def</span> <span class="n">apply</span><span class="o">[</span><span class="kt">T</span><span class="o">](</span><span class="n">body</span><span class="k">:</span> <span class="o">=></span> <span class="n">T</span><span class="o">)(</span><span class="k">implicit</span> <span class="n">executor</span><span class="k">:</span> <span class="kt">ExecutionContext</span><span class="o">)</span><span class="k">:</span> <span class="kt">Future</span><span class="o">[</span><span class="kt">T</span><span class="o">]</span>
<span class="o">}</span>
</code></pre></div>
<p>And we can import a default global one in this case.</p>
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="nn">scala.concurrent.ExecutionContext.Implicits.global</span>
<span class="k">val</span> <span class="n">f</span> <span class="k">=</span> <span class="nc">Future</span> <span class="o">{</span> <span class="cm">/* lenghty computation */</span> <span class="o">}</span>
</code></pre></div>
<p>And <code>global</code> is just a predefined <code>implicit val</code>.</p>
<div class="highlight"><pre><span></span><code><span class="k">object</span> <span class="nc">ExecutionContext</span> <span class="o">{</span>
<span class="k">object</span> <span class="nc">Implicits</span> <span class="o">{</span>
<span class="k">implicit</span> <span class="k">lazy</span> <span class="k">val</span> <span class="n">global</span><span class="k">:</span> <span class="kt">ExecutionContextExecutor</span> <span class="o">=</span> <span class="c1">// ...</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div>
<h3>Implicit conversions</h3>
<p>Say we build a complex number data type and a plus method.</p>
<div class="highlight"><pre><span></span><code><span class="k">case</span> <span class="k">class</span> <span class="nc">Complex</span><span class="o">(</span><span class="n">r</span><span class="k">:</span> <span class="kt">Double</span><span class="o">,</span> <span class="n">i</span><span class="k">:</span> <span class="kt">Double</span><span class="o">)</span>
<span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Complex</span><span class="o">,</span> <span class="n">y</span><span class="k">:</span> <span class="kt">Complex</span><span class="o">)</span><span class="k">:</span> <span class="kt">Complex</span> <span class="o">=</span>
<span class="nc">Complex</span><span class="o">(</span><span class="n">x</span><span class="o">.</span><span class="n">r</span> <span class="o">+</span> <span class="n">y</span><span class="o">.</span><span class="n">r</span><span class="o">,</span> <span class="n">x</span><span class="o">.</span><span class="n">i</span> <span class="o">+</span> <span class="n">y</span><span class="o">.</span><span class="n">i</span><span class="o">)</span>
<span class="n">plus</span><span class="o">(</span><span class="nc">Complex</span><span class="o">(</span><span class="mf">1.0</span><span class="o">,</span> <span class="o">-</span><span class="mf">1.0</span><span class="o">),</span> <span class="nc">Complex</span><span class="o">(</span><span class="mf">2.0</span><span class="o">,</span> <span class="mf">0.0</span><span class="o">))</span> <span class="c1">// Complex(3.0, -1.0)</span>
</code></pre></div>
<p>Note that a complex number <code>2.0+0.0i</code> is also a real number, but we can’t pass it to <code>plus</code> here.</p>
<div class="highlight"><pre><span></span><code><span class="n">plus</span><span class="o">(</span><span class="nc">Complex</span><span class="o">(</span><span class="mf">1.0</span><span class="o">,</span> <span class="o">-</span><span class="mf">1.0</span><span class="o">),</span> <span class="mf">2.0</span><span class="o">)</span> <span class="c1">// type mismatch</span>
</code></pre></div>
<p>We can however convert a <code>Double</code> to a <code>Complex</code>.</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="n">double2complex</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Double</span><span class="o">)</span> <span class="k">=</span> <span class="nc">Complex</span><span class="o">(</span><span class="n">x</span><span class="o">,</span> <span class="mf">0.0</span><span class="o">)</span>
<span class="n">plus</span><span class="o">(</span><span class="nc">Complex</span><span class="o">(</span><span class="mf">1.0</span><span class="o">,</span> <span class="o">-</span><span class="mf">1.0</span><span class="o">),</span> <span class="n">double2complex</span><span class="o">(</span><span class="mf">2.0</span><span class="o">))</span> <span class="c1">// Complex(3.0, -1.0)</span>
</code></pre></div>
<p>And if we make <code>double2complex</code> implicit the compiler can apply automatic conversion for us.</p>
<div class="highlight"><pre><span></span><code><span class="k">implicit</span> <span class="k">def</span> <span class="n">double2complex</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Double</span><span class="o">)</span> <span class="k">=</span> <span class="nc">Complex</span><span class="o">(</span><span class="n">x</span><span class="o">,</span> <span class="mf">0.0</span><span class="o">)</span>
<span class="n">plus</span><span class="o">(</span><span class="nc">Complex</span><span class="o">(</span><span class="mf">1.0</span><span class="o">,</span> <span class="o">-</span><span class="mf">1.0</span><span class="o">),</span> <span class="mf">2.0</span><span class="o">)</span> <span class="c1">// Complex(3.0, -1.0)</span>
</code></pre></div>
<p>Implicit conversions are handy when building specific types from broader, more generic ones, but could lead to surprises if abused. Imagine what happens if we provide an implicit conversion from <code>String</code> to <code>Int</code>.</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Int</span><span class="o">,</span> <span class="n">y</span><span class="k">:</span> <span class="kt">Int</span><span class="o">)</span> <span class="k">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="k">implicit</span> <span class="k">def</span> <span class="n">s2i</span><span class="o">(</span><span class="n">s</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="k">=</span> <span class="n">s</span><span class="o">.</span><span class="n">length</span>
<span class="n">plus</span><span class="o">(</span><span class="s">"a"</span><span class="o">,</span> <span class="s">"bcd"</span><span class="o">)</span> <span class="c1">// => 4!</span>
</code></pre></div>
<h3>Pimp My Library</h3>
<p>Let’s say we’re using the <code>Complex</code> type from another library and would like to add a <code>scale</code> method to it. This is normally not possible without modifying the <code>Complex</code> class source code. However we could build a wrapper for the class with additional methods.</p>
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="nc">RichComplex</span><span class="o">(</span><span class="n">self</span><span class="k">:</span> <span class="kt">Complex</span><span class="o">)</span> <span class="o">{</span>
<span class="k">def</span> <span class="n">scale</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Double</span><span class="o">)</span> <span class="k">=</span> <span class="nc">Complex</span><span class="o">(</span><span class="n">self</span><span class="o">.</span><span class="n">r</span> <span class="o">*</span> <span class="n">x</span><span class="o">,</span> <span class="n">self</span><span class="o">.</span><span class="n">i</span> <span class="o">*</span> <span class="n">x</span><span class="o">)</span>
<span class="o">}</span>
</code></pre></div>
<p>We can also provide an implicit conversion method and use <code>Complex</code> as if it’s also an <code>RichComplex</code>. Here the compiler realizes that there’s no <code>scale(x: Double)</code> method on <code>Complex</code> but there exists an implicit conversion to <code>RichComplex</code> which does.</p>
<div class="highlight"><pre><span></span><code><span class="k">implicit</span> <span class="k">def</span> <span class="n">makeRichComplex</span><span class="o">(</span><span class="n">self</span><span class="k">:</span> <span class="kt">Complex</span><span class="o">)</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">RichComplex</span><span class="o">(</span><span class="n">self</span><span class="o">)</span>
<span class="nc">Complex</span><span class="o">(</span><span class="mf">1.0</span><span class="o">,</span> <span class="o">-</span><span class="mf">1.0</span><span class="o">).</span><span class="n">scale</span><span class="o">(</span><span class="mf">10.0</span><span class="o">)</span> <span class="c1">// => Complex(10.0, 10.0)</span>
</code></pre></div>
<p>If we own the <code>Complex</code> source code, a common pattern is to put enrichment methods (<code>makeRich*</code>) in a companion object and they can be resolved automatically. This is a common technique for library builders to split up complex classes into modules and provide specialization.</p>
<div class="highlight"><pre><span></span><code><span class="k">trait</span> <span class="nc">MyList</span><span class="o">[</span><span class="kt">T</span><span class="o">]</span> <span class="o">{</span>
<span class="c1">// a lot of basic methods</span>
<span class="o">}</span>
<span class="k">class</span> <span class="nc">MyDoubleList</span><span class="o">(</span><span class="n">self</span><span class="k">:</span> <span class="kt">MyList</span><span class="o">[</span><span class="kt">Double</span><span class="o">])</span> <span class="o">{</span>
<span class="c1">// specific methods for Double</span>
<span class="o">}</span>
<span class="k">class</span> <span class="nc">MyKeyValueList</span><span class="o">[</span><span class="kt">K</span><span class="p">,</span> <span class="kt">V</span><span class="o">](</span><span class="n">self</span><span class="k">:</span> <span class="kt">MyList</span><span class="o">[(</span><span class="kt">K</span><span class="p">,</span> <span class="kt">V</span><span class="o">)])</span> <span class="o">{</span>
<span class="c1">// specificmethods for key-value pairs</span>
<span class="o">}</span>
<span class="k">class</span> <span class="nc">MyTextList</span><span class="o">(</span><span class="n">self</span><span class="k">:</span> <span class="kt">MyList</span><span class="o">[</span><span class="kt">String</span><span class="o">])</span> <span class="o">{</span>
<span class="c1">// specific methods for String</span>
<span class="k">def</span> <span class="n">saveAsTextFile</span><span class="o">(</span><span class="n">file</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="k">=</span> <span class="c1">// ...</span>
<span class="o">}</span>
<span class="k">object</span> <span class="nc">MyList</span> <span class="o">{</span>
<span class="k">implicit</span> <span class="k">def</span> <span class="n">makeDoubleList</span><span class="o">(</span><span class="n">self</span><span class="k">:</span> <span class="kt">MyList</span><span class="o">[</span><span class="kt">Double</span><span class="o">])</span> <span class="k">=</span>
<span class="k">new</span> <span class="nc">MyDoubleList</span><span class="o">(</span><span class="n">self</span><span class="o">)</span>
<span class="k">implicit</span> <span class="k">def</span> <span class="n">makeKeyValueList</span><span class="o">[</span><span class="kt">K</span><span class="p">,</span> <span class="kt">V</span><span class="o">](</span><span class="n">self</span><span class="k">:</span> <span class="kt">MyList</span><span class="o">[(</span><span class="kt">K</span><span class="p">,</span> <span class="kt">V</span><span class="o">)])</span> <span class="k">=</span>
<span class="k">new</span> <span class="nc">MyKeyValueList</span><span class="o">(</span><span class="n">self</span><span class="o">)</span>
<span class="k">implicit</span> <span class="k">def</span> <span class="n">makeTextList</span><span class="o">(</span><span class="n">self</span><span class="k">:</span> <span class="kt">MyList</span><span class="o">[</span><span class="kt">String</span><span class="o">])</span> <span class="k">=</span>
<span class="k">new</span> <span class="nc">MyTextList</span><span class="o">(</span><span class="n">self</span><span class="o">)</span>
<span class="o">}</span>
</code></pre></div>
<p>You might have noticed that every time we call a method on an enhanced class, a new object is created. This can be sub-optimal, especially if there are large amount of base objects in a tight loop. The answer to this is <a href="http://docs.scala-lang.org/overviews/core/value-classes.html">value classes</a>. Basically an implicit class that extends <code>AnyVal</code>.</p>
<div class="highlight"><pre><span></span><code><span class="k">implicit</span> <span class="k">class</span> <span class="nc">RichComplex</span><span class="o">(</span><span class="k">val</span> <span class="n">self</span><span class="k">:</span> <span class="kt">Complex</span><span class="o">)</span> <span class="k">extends</span> <span class="nc">AnyVal</span> <span class="o">{</span>
<span class="k">def</span> <span class="n">scale</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Double</span><span class="o">)</span> <span class="k">=</span> <span class="nc">Complex</span><span class="o">(</span><span class="n">self</span><span class="o">.</span><span class="n">r</span> <span class="o">*</span> <span class="n">x</span><span class="o">,</span> <span class="n">self</span><span class="o">.</span><span class="n">i</span> <span class="o">*</span> <span class="n">x</span><span class="o">)</span>
<span class="o">}</span>
</code></pre></div>
<p>The plus side is that now we don’t need the <code>implicit def</code> conversion method any more. The slight down side is that implicit classes cannot be declared at top level. A common practice is to put these classes in a package object so the library user can import it easily, e.g. <code>import com.mydomain.mydsl._</code> with the following example.</p>
<div class="highlight"><pre><span></span><code><span class="k">package</span> <span class="nn">com.mydomain</span>
<span class="k">package</span> <span class="nn">object</span> <span class="n">mydsl</span> <span class="o">{</span>
<span class="k">implicit</span> <span class="k">class</span> <span class="nc">RichComplex</span><span class="o">(</span><span class="k">val</span> <span class="n">self</span><span class="k">:</span> <span class="kt">Complex</span><span class="o">)</span> <span class="k">extends</span> <span class="nc">AnyVal</span> <span class="o">{</span>
<span class="c1">// ...</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div>
<h2>Type classes</h2>
<p>Now that we covered the basic mechanics of implicits, let’s talk about it’s most common use case, type classes. We will start with summing numbers and then generalizing it to other types.</p>
<h3>Summing numbers</h3>
<p>Let’s start with a <code>sum</code> method that sums <code>Int</code>s.</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="n">sum</span><span class="o">(</span><span class="n">xs</span><span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">Int</span><span class="o">])</span> <span class="k">=</span> <span class="n">xs</span><span class="o">.</span><span class="n">reduce</span><span class="o">(</span><span class="k">_</span> <span class="o">+</span> <span class="k">_</span><span class="o">)</span>
</code></pre></div>
<p>This is fairly straight-forward, but what if we want to sum <code>Long</code>, <code>Float</code> and <code>Double</code> as well? The follow code actually doesn’t work because of type erasure.</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="n">sum</span><span class="o">(</span><span class="n">xs</span><span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">Int</span><span class="o">])</span> <span class="k">=</span> <span class="n">xs</span><span class="o">.</span><span class="n">reduce</span><span class="o">(</span><span class="k">_</span> <span class="o">+</span> <span class="k">_</span><span class="o">)</span>
<span class="k">def</span> <span class="n">sum</span><span class="o">(</span><span class="n">xs</span><span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">Long</span><span class="o">])</span> <span class="k">=</span> <span class="n">xs</span><span class="o">.</span><span class="n">reduce</span><span class="o">(</span><span class="k">_</span> <span class="o">+</span> <span class="k">_</span><span class="o">)</span>
<span class="k">def</span> <span class="n">sum</span><span class="o">(</span><span class="n">xs</span><span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">Float</span><span class="o">])</span> <span class="k">=</span> <span class="n">xs</span><span class="o">.</span><span class="n">reduce</span><span class="o">(</span><span class="k">_</span> <span class="o">+</span> <span class="k">_</span><span class="o">)</span>
<span class="k">def</span> <span class="n">sum</span><span class="o">(</span><span class="n">xs</span><span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">Double</span><span class="o">])</span> <span class="k">=</span> <span class="n">xs</span><span class="o">.</span><span class="n">reduce</span><span class="o">(</span><span class="k">_</span> <span class="o">+</span> <span class="k">_</span><span class="o">)</span>
</code></pre></div>
<p>But we noticed that all 4 cases require a <code>_ + _</code> operation. We can define a trait <code>Plus[T]</code> for it, which describes the plus behavior of type <code>T</code>, and 4 instances of it, one for each numeric type we want to generalize over. We call <code>Plus[T]</code> a type class for <code>T</code>. Note that the instances are implicits because we want the compiler to pass them for us.</p>
<div class="highlight"><pre><span></span><code><span class="k">trait</span> <span class="nc">Plus</span><span class="o">[</span><span class="kt">T</span><span class="o">]</span> <span class="o">{</span>
<span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">T</span><span class="o">,</span> <span class="n">y</span><span class="k">:</span> <span class="kt">T</span><span class="o">)</span><span class="k">:</span> <span class="kt">T</span>
<span class="o">}</span>
<span class="k">implicit</span> <span class="k">val</span> <span class="n">intPlus</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">Plus</span><span class="o">[</span><span class="kt">Int</span><span class="o">]</span> <span class="o">{</span>
<span class="k">override</span> <span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Int</span><span class="o">,</span> <span class="n">y</span><span class="k">:</span> <span class="kt">Int</span><span class="o">)</span><span class="k">:</span> <span class="kt">Int</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="o">}</span>
<span class="k">implicit</span> <span class="k">val</span> <span class="n">longPlus</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">Plus</span><span class="o">[</span><span class="kt">Long</span><span class="o">]</span> <span class="o">{</span>
<span class="k">override</span> <span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Long</span><span class="o">,</span> <span class="n">y</span><span class="k">:</span> <span class="kt">Long</span><span class="o">)</span><span class="k">:</span> <span class="kt">Long</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="o">}</span>
<span class="k">implicit</span> <span class="k">val</span> <span class="n">floatPlus</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">Plus</span><span class="o">[</span><span class="kt">Float</span><span class="o">]</span> <span class="o">{</span>
<span class="k">override</span> <span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Float</span><span class="o">,</span> <span class="n">y</span><span class="k">:</span> <span class="kt">Float</span><span class="o">)</span><span class="k">:</span> <span class="kt">Float</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="o">}</span>
<span class="k">implicit</span> <span class="k">val</span> <span class="n">doublePlus</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">Plus</span><span class="o">[</span><span class="kt">Double</span><span class="o">]</span> <span class="o">{</span>
<span class="k">override</span> <span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Double</span><span class="o">,</span> <span class="n">y</span><span class="k">:</span> <span class="kt">Double</span><span class="o">)</span><span class="k">:</span> <span class="kt">Double</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
<span class="o">}</span>
</code></pre></div>
<p>How we can rewrite our <code>sum</code> method in a more generic way.</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="n">sum</span><span class="o">[</span><span class="kt">T</span><span class="o">](</span><span class="n">xs</span><span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">T</span><span class="o">])(</span><span class="k">implicit</span> <span class="n">p</span><span class="k">:</span> <span class="kt">Plus</span><span class="o">[</span><span class="kt">T</span><span class="o">])</span> <span class="k">=</span> <span class="n">xs</span><span class="o">.</span><span class="n">reduce</span><span class="o">(</span><span class="n">p</span><span class="o">.</span><span class="n">plus</span><span class="o">)</span>
<span class="n">sum</span><span class="o">(</span><span class="nc">List</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">3</span><span class="o">))</span> <span class="c1">// => 6</span>
<span class="n">sum</span><span class="o">(</span><span class="nc">List</span><span class="o">(</span><span class="mf">0.1</span><span class="o">,</span> <span class="mf">0.2</span><span class="o">,</span> <span class="mf">0.3</span><span class="o">))</span> <span class="c1">// => 0.6</span>
</code></pre></div>
<p>This is nice but we still have to implement 4 <code>Plus[T]</code> instances. Lucky for us, there’s already a predefined <code>Numeric[T]</code> type class in Scala, so we can simplify the above.</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="n">sum</span><span class="o">[</span><span class="kt">T</span><span class="o">](</span><span class="n">xs</span><span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">T</span><span class="o">])(</span><span class="k">implicit</span> <span class="n">num</span><span class="k">:</span> <span class="kt">Numeric</span><span class="o">[</span><span class="kt">T</span><span class="o">])</span> <span class="k">=</span> <span class="n">xs</span><span class="o">.</span><span class="n">reduce</span><span class="o">(</span><span class="n">num</span><span class="o">.</span><span class="n">plus</span><span class="o">)</span>
</code></pre></div>
<p>This works for the numeric types in Scala but not necessarily other types that exhibit similar behavior, e.g. <code>Complex</code>, <code>Rational</code>. We can even further generalize the plus operation to non-numerical types, like the union of 2 sets.</p>
<h3>Semigroup</h3>
<p>Now we start noticing a common pattern among these use cases, a type <code>T</code> and a binary operation <code>plus</code> of <code>(T, T) => T</code>. This is known as a <a href="https://en.wikipedia.org/wiki/Semigroup">semigroup</a> in abstract algebra, and the plus operation is required to be associative, i.e. <code>(x + y) + z = x + (y + z)</code>. We can now support <code>Set[U]</code> by rewriting <code>sum</code> with <code>Semigroup[T]</code>.</p>
<div class="highlight"><pre><span></span><code><span class="k">trait</span> <span class="nc">Semigroup</span><span class="o">[</span><span class="kt">T</span><span class="o">]</span> <span class="o">{</span>
<span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">T</span><span class="o">,</span> <span class="n">y</span><span class="k">:</span> <span class="kt">T</span><span class="o">)</span><span class="k">:</span> <span class="kt">T</span>
<span class="o">}</span>
<span class="k">implicit</span> <span class="k">def</span> <span class="n">numSg</span><span class="o">(</span><span class="k">implicit</span> <span class="n">num</span><span class="k">:</span> <span class="kt">Numeric</span><span class="o">[</span><span class="kt">T</span><span class="o">])</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">Semigroup</span><span class="o">[</span><span class="kt">T</span><span class="o">]</span> <span class="o">{</span>
<span class="k">override</span> <span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">T</span><span class="o">,</span> <span class="n">y</span><span class="k">:</span> <span class="kt">T</span><span class="o">)</span><span class="k">:</span> <span class="kt">T</span> <span class="o">=</span> <span class="n">num</span><span class="o">.</span><span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="o">,</span> <span class="n">y</span><span class="o">)</span>
<span class="o">}</span>
<span class="k">implicit</span> <span class="k">def</span> <span class="n">setSg</span><span class="o">[</span><span class="kt">U</span><span class="o">]</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">Semigroup</span><span class="o">[</span><span class="kt">Set</span><span class="o">[</span><span class="kt">U</span><span class="o">]]</span> <span class="o">{</span>
<span class="k">override</span> <span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Set</span><span class="o">[</span><span class="kt">U</span><span class="o">],</span> <span class="n">y</span><span class="k">:</span> <span class="kt">Set</span><span class="o">[</span><span class="kt">U</span><span class="o">])</span><span class="k">:</span> <span class="kt">Set</span><span class="o">[</span><span class="kt">U</span><span class="o">]</span> <span class="k">=</span> <span class="n">x</span> <span class="o">++</span> <span class="n">y</span>
<span class="o">}</span>
<span class="k">def</span> <span class="n">sum</span><span class="o">[</span><span class="kt">T</span><span class="o">](</span><span class="n">xs</span><span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">T</span><span class="o">])(</span><span class="k">implicit</span> <span class="n">sg</span><span class="k">:</span> <span class="kt">Semigroup</span><span class="o">[</span><span class="kt">T</span><span class="o">])</span> <span class="k">=</span> <span class="n">xs</span><span class="o">.</span><span class="n">reduce</span><span class="o">(</span><span class="n">sg</span><span class="o">.</span><span class="n">plus</span><span class="o">)</span>
<span class="n">sum</span><span class="o">(</span><span class="nc">List</span><span class="o">(</span><span class="nc">Set</span><span class="o">(</span><span class="s">"a"</span><span class="o">,</span> <span class="s">"b"</span><span class="o">),</span> <span class="nc">Set</span><span class="o">(</span><span class="s">"a"</span><span class="o">,</span> <span class="s">"c"</span><span class="o">),</span> <span class="nc">Set</span><span class="o">(</span><span class="s">"d"</span><span class="o">)))</span> <span class="c1">// => Set("a", "b", "c", "d")</span>
</code></pre></div>
<p>The method signature for <code>sum</code> is a bit hard to read though, since we have a type parameter <code>[T]</code> before the argument list <code>(xs: List[T])</code>, and a implicit argument <code>sg: Semigroup[T]</code> after that describes the behavior of <code>T</code>. This can be rewritten as a context bound, <code>[T: Semigroup]</code>, to indicate that there exists a <code>Semigroup[T]</code> instance, but not explicitly given a name inside <code>sum</code>. The inside the function <code>implicitly[Semigroup[T]]</code> recovers the name.</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="n">sum</span><span class="o">[</span><span class="kt">T:</span> <span class="kt">Semigroup</span><span class="o">](</span><span class="n">xs</span><span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">T</span><span class="o">])</span> <span class="k">=</span> <span class="o">{</span>
<span class="k">val</span> <span class="n">sg</span> <span class="k">=</span> <span class="n">implicitly</span><span class="o">[</span><span class="kt">Semigroup</span><span class="o">[</span><span class="kt">T</span><span class="o">]]</span>
<span class="n">xs</span><span class="o">.</span><span class="n">reduce</span><span class="o">(</span><span class="n">sg</span><span class="o">.</span><span class="n">plus</span><span class="o">)</span>
<span class="o">}</span>
</code></pre></div>
<p>And if we look at the source code of <code>implicitly</code>, it simply does what we did with <code>(implicit sg: Semigroup[T])</code> with a funny comment.</p>
<div class="highlight"><pre><span></span><code><span class="c1">// for summoning implicit values from the nether world </span>
<span class="k">def</span> <span class="n">implicitly</span><span class="o">[</span><span class="kt">T</span><span class="o">](</span><span class="k">implicit</span> <span class="n">e</span><span class="k">:</span> <span class="kt">T</span><span class="o">)</span> <span class="k">=</span> <span class="n">e</span>
</code></pre></div>
<p>One common practice in Scala is to use tuples for lightweight data representation, e.g. rows from a data source. But how do we sum tuples? Say we have a list of <code>(Int, Double, Set[String])</code>, logically we want to sum the first, second and third field separately. Since we already have <code>Semigroup[T]</code> on <code>Int</code>, <code>Double</code> and <code>Set[U]</code>, we can compose them into a new semigroup. Note that this semigroup not only works for <code>(Int, Double, Set[String])</code> but any tuple 3 with arbitrary member types.</p>
<div class="highlight"><pre><span></span><code><span class="k">implicit</span> <span class="k">def</span> <span class="n">t3Sg</span><span class="o">[</span><span class="kt">A:</span> <span class="kt">Semigroup</span><span class="p">,</span> <span class="kt">B:</span> <span class="kt">Semigroup</span><span class="p">,</span> <span class="kt">C:</span> <span class="kt">Semigroup</span><span class="o">]</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">Semigroup</span><span class="o">[(</span><span class="kt">A</span><span class="p">,</span> <span class="kt">B</span><span class="p">,</span> <span class="kt">C</span><span class="o">)]</span> <span class="o">{</span>
<span class="k">val</span> <span class="n">sgA</span> <span class="k">=</span> <span class="n">implicitly</span><span class="o">[</span><span class="kt">Semigroup</span><span class="o">[</span><span class="kt">A</span><span class="o">]]</span>
<span class="k">val</span> <span class="n">sgB</span> <span class="k">=</span> <span class="n">implicitly</span><span class="o">[</span><span class="kt">Semigroup</span><span class="o">[</span><span class="kt">B</span><span class="o">]]</span>
<span class="k">val</span> <span class="n">sgC</span> <span class="k">=</span> <span class="n">implicitly</span><span class="o">[</span><span class="kt">Semigroup</span><span class="o">[</span><span class="kt">C</span><span class="o">]]</span>
<span class="o">(</span><span class="n">sgA</span><span class="o">.</span><span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="o">.</span><span class="n">_1</span><span class="o">,</span> <span class="n">y</span><span class="o">.</span><span class="n">_1</span><span class="o">),</span> <span class="n">sgB</span><span class="o">.</span><span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="o">.</span><span class="n">_2</span><span class="o">,</span> <span class="n">y</span><span class="o">.</span><span class="n">_2</span><span class="o">),</span> <span class="n">sgC</span><span class="o">.</span><span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="o">.</span><span class="n">_3</span><span class="o">,</span> <span class="n">y</span><span class="o">.</span><span class="n">_3</span><span class="o">))</span>
<span class="o">}</span>
<span class="n">sum</span><span class="o">(</span><span class="nc">List</span><span class="o">(</span>
<span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="mf">0.5</span><span class="o">,</span> <span class="nc">Set</span><span class="o">(</span><span class="s">"a"</span><span class="o">)),</span>
<span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="mf">1.5</span><span class="o">,</span> <span class="nc">Set</span><span class="o">(</span><span class="s">"b"</span><span class="o">,</span> <span class="s">"c"</span><span class="o">)),</span>
<span class="o">(</span><span class="mi">3</span><span class="o">,</span> <span class="mf">2.5</span><span class="o">,</span> <span class="nc">Set</span><span class="o">(</span><span class="s">"a"</span><span class="o">,</span> <span class="s">"b"</span><span class="o">,</span> <span class="s">"d"</span><span class="o">))))</span>
<span class="c1">// => (6, 4.5, Set("a", "b", "c", "d"))</span>
</code></pre></div>
<p>Obviously we don’t want to handcraft this for tuples from 2 to 22. Libraries like <a href="https://github.com/twitter/algebird">Algebird</a> already include these common ones.</p>
<p>We can even generalize semigroup to maps. For two maps of <code>Map[K, V]</code> and a <code>Semigroup[V]</code>, we can sum the maps by summing values of the same key with the given semigroup.</p>
<div class="highlight"><pre><span></span><code><span class="k">implicit</span> <span class="k">def</span> <span class="n">mSg</span><span class="o">[</span><span class="kt">K</span><span class="p">,</span> <span class="kt">V:</span> <span class="kt">Semigroup</span><span class="o">]</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">Semigroup</span><span class="o">[</span><span class="kt">Map</span><span class="o">[</span><span class="kt">K</span><span class="p">,</span> <span class="kt">V</span><span class="o">]]</span> <span class="o">{</span>
<span class="k">override</span> <span class="k">def</span> <span class="n">plus</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Map</span><span class="o">[</span><span class="kt">K</span><span class="p">,</span> <span class="kt">V</span><span class="o">],</span> <span class="n">y</span><span class="k">:</span> <span class="kt">Map</span><span class="o">[</span><span class="kt">K</span><span class="p">,</span> <span class="kt">V</span><span class="o">])</span><span class="k">:</span> <span class="kt">Map</span><span class="o">[</span><span class="kt">K</span><span class="p">,</span> <span class="kt">V</span><span class="o">]</span> <span class="k">=</span>
<span class="n">x</span> <span class="o">++</span> <span class="n">y</span><span class="o">.</span><span class="n">map</span> <span class="o">{</span> <span class="k">case</span> <span class="o">(</span><span class="n">k</span><span class="o">,</span> <span class="n">rv</span><span class="o">)</span> <span class="k">=></span>
<span class="k">val</span> <span class="n">v</span> <span class="k">=</span> <span class="n">x</span><span class="o">.</span><span class="n">get</span><span class="o">(</span><span class="n">k</span><span class="o">)</span> <span class="k">match</span> <span class="o">{</span>
<span class="k">case</span> <span class="nc">Some</span><span class="o">(</span><span class="n">lv</span><span class="o">)</span> <span class="k">=></span> <span class="n">implicitly</span><span class="o">[</span><span class="kt">Semigroup</span><span class="o">[</span><span class="kt">V</span><span class="o">]].</span><span class="n">plus</span><span class="o">(</span><span class="n">lv</span><span class="o">,</span> <span class="n">rv</span><span class="o">)</span>
<span class="k">case</span> <span class="nc">None</span> <span class="k">=></span> <span class="n">rv</span>
<span class="o">}</span>
<span class="o">(</span><span class="n">k</span><span class="o">,</span> <span class="n">v</span><span class="o">)</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="k">val</span> <span class="n">m1</span> <span class="k">=</span> <span class="nc">Map</span><span class="o">(</span>
<span class="s">"a"</span> <span class="o">-></span> <span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="mf">0.5</span><span class="o">,</span> <span class="nc">Set</span><span class="o">(</span><span class="s">"a"</span><span class="o">)),</span>
<span class="s">"b"</span> <span class="o">-></span> <span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="mf">1.5</span><span class="o">,</span> <span class="nc">Set</span><span class="o">(</span><span class="s">"b"</span><span class="o">,</span> <span class="s">"c"</span><span class="o">)),</span>
<span class="s">"c"</span> <span class="o">-></span> <span class="o">(</span><span class="mi">3</span><span class="o">,</span> <span class="mf">2.5</span><span class="o">,</span> <span class="nc">Set</span><span class="o">(</span><span class="s">"a"</span><span class="o">,</span> <span class="s">"b"</span><span class="o">,</span> <span class="s">"c"</span><span class="o">)))</span>
<span class="k">val</span> <span class="n">m2</span> <span class="k">=</span> <span class="nc">Map</span><span class="o">(</span>
<span class="s">"a"</span> <span class="o">-></span> <span class="o">(</span><span class="mi">10</span><span class="o">,</span> <span class="mf">10.0</span><span class="o">,</span> <span class="nc">Set</span><span class="o">(</span><span class="s">"a"</span><span class="o">,</span> <span class="s">"b"</span><span class="o">)),</span>
<span class="s">"b"</span> <span class="o">-></span> <span class="o">(</span><span class="mi">20</span><span class="o">,</span> <span class="mf">20.0</span><span class="o">,</span> <span class="nc">Set</span><span class="o">(</span><span class="s">"c"</span><span class="o">,</span> <span class="s">"d"</span><span class="o">,</span> <span class="s">"e"</span><span class="o">)),</span>
<span class="s">"d"</span> <span class="o">-></span> <span class="o">(</span><span class="mi">40</span><span class="o">,</span> <span class="mf">100.0</span><span class="o">,</span> <span class="nc">Set</span><span class="o">(</span><span class="s">"z"</span><span class="o">)))</span>
<span class="n">sum</span><span class="o">(</span><span class="nc">List</span><span class="o">(</span><span class="n">m1</span><span class="o">,</span> <span class="n">m2</span><span class="o">))</span>
<span class="cm">/*</span>
<span class="cm">=> Map(</span>
<span class="cm"> "a" -> (11, 10.5, Set("a", "b")),</span>
<span class="cm"> "b" -> (22, 21.5, Set("b", "c", "d", "e")),</span>
<span class="cm"> "c" -> (3, 2.5, Set("a", "b", "c")),</span>
<span class="cm"> "d" -> (40, 100.0, Set("z")))</span>
<span class="cm">*/</span>
</code></pre></div>
<h2>Summary</h2>
<p>That summarizes some main use cases of implicits. Here are some references.</p>
<ul>
<li><a href="http://www.scala-lang.org/api/current/scala/math/Ordering.html">Ordering</a> and <a href="http://www.scala-lang.org/api/current/scala/math/Numeric.html">Numeric</a> type classes in Scala</li>
<li><a href="https://github.com/twitter/algebird">Algebird</a> - Abstract Algebra for Scala</li>
<li>My slides on <a href="http://www.lyh.me/slides/type-classes.html">type classes</a> and <a href="http://www.lyh.me/slides/semigroups.html">semigroups</a></li>
<li>Another excellent <a href="http://www.lihaoyi.com/post/ImplicitDesignPatternsinScala.html">blog post</a> on implicit design patterns by Li Haoyi</li>
</ul>
<p>We didn’t discuss some more advanced topics like implicit resolution precedence and priority trick. Here are some more references.</p>
<ul>
<li><a href="http://stackoverflow.com/questions/5598085/where-does-scala-look-for-implicits">Where does Scala look for implicits?</a></li>
<li><a href="http://eed3si9n.com/implicit-parameter-precedence-again">implicit parameter precedence again</a></li>
<li><a href="https://gist.github.com/retronym/228673#file-low-priority-implicits-scala">Implicit prioritisation</a></li>
</ul>
</div>
<!-- /.entry-content -->
<hr />
<!-- AddThis Button BEGIN -->
<div class="addthis_toolbox addthis_default_style">
<a class="addthis_button_facebook_like" fb:like:layout="button_count"></a>
<a class="addthis_button_tweet"></a>
<a class="addthis_button_google_plusone" g:plusone:size="medium"></a>
</div>
<!-- AddThis Button END -->
<hr/>
<section class="comments" id="comments">
<h2>Comments</h2>
<div id="disqus_thread"></div>
<script type="text/javascript">
/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
var disqus_shortname = 'lyh'; // required: replace example with your forum shortname
var disqus_config = function () {
this.language = "en";
this.page.identifier = '2017-04-21-implicits';
this.page.url = 'https://www.lyh.me/implicits.html';
};
/* * * DON'T EDIT BELOW THIS LINE * * */
(function () {
var dsq = document.createElement('script');
dsq.type = 'text/javascript';
dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by
Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>
</section>
</article>
</section>
</div>
<div class="col-sm-3" id="sidebar">
<aside>
<div id="aboutme">
<p>
<img width="100%" class="img-thumbnail" src="https://www.lyh.me//avatar.jpg"/>
</p>
<p>
<strong>About Neville Li</strong><br/>
Data infrastructure @<a href="https://twitter.com/Spotify">Spotify</a>, ex-@<a href="https://twitter.com/Yahoo">Yahoo</a> search, creator of <a href="https://github.com/spotify/scio">Scio</a>, technical cave & wreck diver, lefty guitar player
</p>
</div><!-- Sidebar -->
<section class="well well-sm">
<ul class="list-group list-group-flush">
<!-- Sidebar/Social -->
<li class="list-group-item">
<h4><i class="fa fa-home fa-lg"></i><span class="icon-label">Social</span></h4>
<ul class="list-group" id="social">
<li class="list-group-item"><a href="https://open.spotify.com/user/sinisa_lyh"><i class="fa fa-spotify fa-lg"></i> Spotify</a></li>
<li class="list-group-item"><a href="https://github.com/nevillelyh"><i class="fa fa-github-square fa-lg"></i> GitHub</a></li>
<li class="list-group-item"><a href="https://twitter.com/sinisa_lyh"><i class="fa fa-twitter-square fa-lg"></i> Twitter</a></li>
<li class="list-group-item"><a href="https://www.slideshare.net/sinisalyh"><i class="fa fa-slideshare fa-lg"></i> SlideShare</a></li>
<li class="list-group-item"><a href="https://www.youtube.com/user/sinisalyh/videos"><i class="fa fa-youtube-square fa-lg"></i> YouTube</a></li>
<li class="list-group-item"><a href="https://www.instagram.com/sinisa/"><i class="fa fa-instagram fa-lg"></i> Instagram</a></li>
<li class="list-group-item"><a href="https://www.flickr.com/photos/sinisa_lyh"><i class="fa fa-flickr fa-lg"></i> Flickr</a></li>
</ul>
</li>
<!-- End Sidebar/Social -->
<!-- Sidebar/Recent Posts -->
<li class="list-group-item">
<h4><i class="fa fa-home fa-lg"></i><span class="icon-label">Recent Posts</span></h4>
<ul class="list-group" id="recentposts">
<li class="list-group-item"><a href="https://www.lyh.me/magnolify.html">Magnolify</a></li>
<li class="list-group-item"><a href="https://www.lyh.me/featran.html">Featran</a></li>
<li class="list-group-item"><a href="https://www.lyh.me/automatic-type-class-derivation-with-shapeless.html">Automatic type-class derivation with Shapeless</a></li>
<li class="list-group-item"><a href="https://www.lyh.me/lambda-serialization.html">Lambda serialization</a></li>
<li class="list-group-item"><a href="https://www.lyh.me/lawfulness-of-aggregatebykey.html">Lawfulness of aggregateByKey</a></li>
</ul>
</li>
<!-- End Sidebar/Recent Posts -->
<!-- Sidebar/Categories -->
<li class="list-group-item">
<h4><i class="fa fa-home fa-lg"></i><span class="icon-label">Categories</span></h4>
<ul class="list-group" id="categories">
<li class="list-group-item">
<a href="https://www.lyh.me/category/code.html"><i class="fa fa-folder-open fa-lg"></i>code</a>
</li>
<li class="list-group-item">
<a href="https://www.lyh.me/category/misc.html"><i class="fa fa-folder-open fa-lg"></i>misc</a>
</li>
</ul>
</li>
<!-- End Sidebar/Categories -->
<!-- Sidebar/Twitter Timeline -->
<li class="list-group-item">
<h4><i class="fa fa-twitter fa-lg"></i><span class="icon-label">Latest Tweets</span></h4>
<div id="twitter_timeline">
<a class="twitter-timeline" data-width="250" data-height="300" data-dnt="true" data-theme="light" href="https://twitter.com/sinisa_lyh">Tweets by sinisa_lyh</a> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
</li>
<!-- End Sidebar/Twitter Timeline -->
</ul>
</section>
<!-- End Sidebar --> </aside>
</div>
</div>
</div>
<!-- End Content Container -->
<footer>
<div class="container">
<hr>
<div class="row">
<div class="col-xs-10">© 2020 Neville Li
· Powered by <a href="https://github.com/getpelican/pelican-themes/tree/master/pelican-bootstrap3" target="_blank">pelican-bootstrap3</a>,
<a href="http://docs.getpelican.com/" target="_blank">Pelican</a>,
<a href="http://getbootstrap.com" target="_blank">Bootstrap</a> <p><small> <a rel="license" href="https://creativecommons.org/licenses/by-nc/4.0/deed.en"><img alt="Creative Commons License" style="border-width:0" src="//i.creativecommons.org/l/by-nc/4.0/80x15.png" /></a>
Content
licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-nc/4.0/deed.en">Creative Commons Attribution-NonCommercial 4.0 International License</a>, except where indicated otherwise.
</small></p>
</div>
<div class="col-xs-2"><p class="pull-right"><i class="fa fa-arrow-up"></i> <a href="#">Back to top</a></p></div>
</div>
</div>
</footer>
<script src="https://www.lyh.me/theme/js/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="https://www.lyh.me/theme/js/bootstrap.min.js"></script>
<!-- Enable responsive features in IE8 with Respond.js (https://github.com/scottjehl/Respond) -->
<script src="https://www.lyh.me/theme/js/respond.min.js"></script>
<!-- Disqus -->
<script type="text/javascript">
/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
var disqus_shortname = 'lyh'; // required: replace example with your forum shortname
/* * * DON'T EDIT BELOW THIS LINE * * */
(function () {
var s = document.createElement('script');
s.async = true;
s.type = 'text/javascript';
s.src = '//' + disqus_shortname + '.disqus.com/count.js';
(document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
}());
</script>
<!-- End Disqus Code -->
<!-- Google Analytics -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-6988688-5']);
_gaq.push(['_trackPageview']);
(function () {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- End Google Analytics Code -->
<script type="text/javascript">var addthis_config = {"data_track_addressbar": true};</script>
<script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=sinisalyh"></script>
</body>
</html>