1
1
---
2
2
layout : doc-page
3
- title : Typeclass Derivation
3
+ title : Type Class Derivation
4
4
---
5
5
6
6
Type class derivation is a way to automatically generate given instances for type classes which satisfy some simple
@@ -28,8 +28,9 @@ We say that `Tree` is the _deriving type_ and that the `Eq`, `Ordering` and `Sho
28
28
29
29
### Types supporting ` derives ` clauses
30
30
31
- Any data type with an available instance of the ` Mirror ` type class supports ` derives ` clauses. Instances of the
32
- ` Mirror ` type class are generated automatically by the compiler for,
31
+ All data types can have a ` derives ` clause. This document focuses primarily on data types which also have an instance
32
+ of the ` Mirror ` type class available. Instances of the ` Mirror ` type class are generated automatically by the compiler
33
+ for,
33
34
34
35
+ enums and enum cases
35
36
+ case classes and case objects
@@ -103,6 +104,7 @@ Mirror.Product {
103
104
104
105
def fromProduct (p : Product ): MirroredMonoType =
105
106
new Branch (...)
107
+ }
106
108
107
109
// Mirror for Leaf
108
110
Mirror .Product {
@@ -114,6 +116,7 @@ Mirror.Product {
114
116
115
117
def fromProduct (p : Product ): MirroredMonoType =
116
118
new Leaf (...)
119
+ }
117
120
```
118
121
119
122
Note the following properties of ` Mirror ` types,
@@ -131,24 +134,29 @@ Note the following properties of `Mirror` types,
131
134
132
135
### Type classes supporting automatic deriving
133
136
134
- A trait or class can appear in a `derives` clause if its companion object defines a method named `derived`. The type
135
- and implementation of a `derived` method for a type class `TC[_]` are arbitrary but it is typically of the following
136
- form,
137
+ A trait or class can appear in a ` derives ` clause if its companion object defines a method named ` derived ` . The
138
+ signature and implementation of a ` derived ` method for a type class ` TC[_] ` are arbitrary but it is typically of the
139
+ following form,
137
140
138
141
``` scala
139
142
def derived [T ] given Mirror .Of [T ]: TC [T ] = ...
140
143
```
141
144
142
145
That is, the ` derived ` method takes a given parameter of (some subtype of) type ` Mirror ` which defines the shape of
143
- the deriving type `T` , and computes the typeclass implementation according to that shape. This is all that the
146
+ the deriving type ` T ` , and computes the type class implementation according to that shape. This is all that the
144
147
provider of an ADT with a ` derives ` clause has to know about the derivation of a type class instance.
145
148
149
+ Note that ` derived ` methods may have given ` Mirror ` arguments indirectly (eg. by having a given argument which in turn
150
+ has a given ` Mirror ` , or not at all (eg. they might use some completely different user-provided mechanism, for
151
+ instance using Dotty macros or runtime reflection). We expect that (direct or indirect) ` Mirror ` based implementations
152
+ will be the most common and that is what this document emphasises.
153
+
146
154
Type class authors will most likely use higher level derivation or generic programming libraries to implement
147
- `derived` methods. The rest of this page gives an example of how a `derived` method might be implemented using _only_
148
- the low level facilities described above and Dotty ' s general metaprogramming features. It is not anticipated that type
149
- class authors would normally implement a `derived` method in this way, however this walkthrough can be taken as a
150
- guide for authors of the higher level derivation libraries that we expect typical type class authors will use (for a
151
- fully worked out example of such a library, see [shapeless 3 ](https:// github.com/ milessabin/ shapeless/ tree/ shapeless- 3 )).
155
+ ` derived ` methods. An example of how a ` derived ` method might be implemented using _ only_ the low level facilities
156
+ described above and Dotty's general metaprogramming features is provided below . It is not anticipated that type class
157
+ authors would normally implement a ` derived ` method in this way, however this walkthrough can be taken as a guide for
158
+ authors of the higher level derivation libraries that we expect typical type class authors will use (for a fully
159
+ worked out example of such a library, see [ shapeless 3] ( https://github.com/milessabin/shapeless/tree/shapeless-3 ) ).
152
160
153
161
#### How to write a type class ` derived ` method using low level mechanisms
154
162
@@ -341,8 +349,8 @@ The framework described here enables all three of these approaches without manda
341
349
342
350
### Deriving instances elsewhere
343
351
344
- Sometimes one would like to derive a typeclass instance for an ADT after the ADT is defined, without being able to
345
- change the code of the ADT itself. To do this , simply define an instance using the `derived` method of the typeclass
352
+ Sometimes one would like to derive a type class instance for an ADT after the ADT is defined, without being able to
353
+ change the code of the ADT itself. To do this, simply define an instance using the ` derived ` method of the type class
346
354
as right-hand side. E.g, to implement ` Ordering ` for ` Option ` define,
347
355
348
356
``` scala
@@ -365,7 +373,7 @@ ConstrApps ::= ConstrApp {‘with’ ConstrApp}
365
373
366
374
### Discussion
367
375
368
- This typeclass derivation framework is intentionally very small and low- level. There are essentially two pieces of
376
+ This type class derivation framework is intentionally very small and low-level. There are essentially two pieces of
369
377
infrastructure in compiler-generated ` Mirror ` instances,
370
378
371
379
+ type members encoding properties of the mirrored types.
@@ -380,7 +388,7 @@ feature small enough to make it possible to provide `Mirror` instances _uncondit
380
388
Whilst ` Mirrors ` encode properties precisely via type members, the value level ` ordinal ` and ` fromProduct ` are
381
389
somewhat weakly typed (because they are defined in terms of ` MirroredMonoType ` ) just like the members of ` Product ` .
382
390
This means that code for generic type classes has to ensure that type exploration and value selection proceed in
383
- lockstep and it has to assert this conformance in some places using casts. If generic typeclasses are correctly
391
+ lockstep and it has to assert this conformance in some places using casts. If generic type classes are correctly
384
392
written these casts will never fail.
385
393
386
394
As mentioned, however, the compiler-provided mechansim is intentionally very low level and it is anticipated that
0 commit comments