Skip to content

Commit 0dda15c

Browse files
committed
Respond to reviews
1 parent efb8576 commit 0dda15c

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

docs/docs/reference/contextual/derivation.md

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
layout: doc-page
3-
title: Typeclass Derivation
3+
title: Type Class Derivation
44
---
55

66
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
2828

2929
### Types supporting `derives` clauses
3030

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,
3334

3435
+ enums and enum cases
3536
+ case classes and case objects
@@ -103,6 +104,7 @@ Mirror.Product {
103104

104105
def fromProduct(p: Product): MirroredMonoType =
105106
new Branch(...)
107+
}
106108

107109
// Mirror for Leaf
108110
Mirror.Product {
@@ -114,6 +116,7 @@ Mirror.Product {
114116

115117
def fromProduct(p: Product): MirroredMonoType =
116118
new Leaf(...)
119+
}
117120
```
118121

119122
Note the following properties of `Mirror` types,
@@ -131,24 +134,29 @@ Note the following properties of `Mirror` types,
131134

132135
### Type classes supporting automatic deriving
133136

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,
137140

138141
```scala
139142
def derived[T] given Mirror.Of[T]: TC[T] = ...
140143
```
141144

142145
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
144147
provider of an ADT with a `derives` clause has to know about the derivation of a type class instance.
145148

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+
146154
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)).
152160

153161
#### How to write a type class `derived` method using low level mechanisms
154162

@@ -341,8 +349,8 @@ The framework described here enables all three of these approaches without manda
341349

342350
### Deriving instances elsewhere
343351

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
346354
as right-hand side. E.g, to implement `Ordering` for `Option` define,
347355

348356
```scala
@@ -365,7 +373,7 @@ ConstrApps ::= ConstrApp {‘with’ ConstrApp}
365373

366374
### Discussion
367375

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
369377
infrastructure in compiler-generated `Mirror` instances,
370378

371379
+ type members encoding properties of the mirrored types.
@@ -380,7 +388,7 @@ feature small enough to make it possible to provide `Mirror` instances _uncondit
380388
Whilst `Mirrors` encode properties precisely via type members, the value level `ordinal` and `fromProduct` are
381389
somewhat weakly typed (because they are defined in terms of `MirroredMonoType`) just like the members of `Product`.
382390
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
384392
written these casts will never fail.
385393

386394
As mentioned, however, the compiler-provided mechansim is intentionally very low level and it is anticipated that

tests/pos/no-mirror-derives.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Foo derives Bar
2+
3+
trait Bar[T]
4+
object Bar {
5+
def derived[T]: Bar[T] = new Bar[T] {}
6+
}

0 commit comments

Comments
 (0)