You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Port ""Add "Exact mechanism" section to derivation.md"" to main (#16219)
Branch `fix-derivation-main` was created as follows:
```
# Make sure main is up to date
git checkout fix-derivation
git checkout -b fix-derivation-main
git rebase --onto main language-reference-stable fix-derivation-main
# Make PR into main from fix-derivation-main
```
We say that `Tree` is the _deriving type_ and that the `Eq`, `Ordering` and `Show` instances are _derived instances_.
28
28
29
-
**Note:** The access to `derived` above is a normal access, therefore if there are multiple definitions of `derived` in the type class, overloading resolution applies.
30
-
31
-
**Note:**`derived` can be used manually, this is useful when you do not have control over the definition. For example we can implement an `Ordering` for `Option`s like so:
29
+
**Note:**`derived` can be used manually, this is useful when you do not have control over the definition. For example we can implement `Ordering` for `Option`s like so:
32
30
33
31
```scala
34
32
given [T:Ordering]:Ordering[Option[T]] =Ordering.derived
35
33
```
36
34
37
35
It is discouraged to directly refer to the `derived` member if you can use a `derives` clause instead.
38
36
39
-
All data types can have a `derives` clause. This document focuses primarily on data types which also have a given instance
37
+
## Exact mechanism
38
+
In the following, when type arguments are enumerated and the first index evaluates to a larger value than the last, then there are actually no arguments, for example: `A[T_2, ..., T_1]` means `A`.
39
+
40
+
For a class/trait/object/enum `DerivingType[T_1, ..., T_N] derives TC`, a derived instance is created in `DerivingType`'s companion object (or `DerivingType` itself if it is an object).
41
+
42
+
The general "shape" of the derived instance is as follows:
43
+
```scala
44
+
given [...](using ...):TC[ ... DerivingType[...] ... ] =TC.derived
45
+
```
46
+
`TC.derived` should be an expression that conforms to the expected type on the left, potentially elaborated using term and/or type inference.
47
+
48
+
**Note:**`TC.derived` is a normal access, therefore if there are multiple definitions of `TC.derived`, overloading resolution applies.
49
+
50
+
What the derived instance precisely looks like depends on the specifics of `DerivingType` and `TC`, we first examine `TC`:
51
+
52
+
### `TC` takes 1 parameter `F`
53
+
54
+
Therefore `TC` is defined as `TC[F[A_1, ..., A_K]]` (`TC[F]` if `K == 0`) for some `F`.
55
+
There are two further cases depending on the kinds of arguments:
56
+
57
+
#### `F` and all arguments of `DerivingType` have kind `*`
58
+
**Note:**`K == 0` in this case.
59
+
60
+
The generated instance is then:
61
+
```scala
62
+
given [T_1:TC, ..., T_N:TC]:TC[DerivingType[T_1, ..., T_N]] =TC.derived
63
+
```
64
+
65
+
This is the most common case, and is the one that was highlighted in the introduction.
66
+
67
+
**Note:** The `[T_i: TC, ...]` introduces a `(using TC[T_i], ...)`, more information in [Context Bounds](./context-bounds.md).
68
+
This allows the `derived` member to access these evidences.
69
+
70
+
**Note:** If `N == 0` the above means:
71
+
```scala
72
+
givenTC[DerivingType] =TC.derived
73
+
```
74
+
For example, the class
75
+
```scala
76
+
caseclassPoint(x: Int, y: Int) derivesOrdering
77
+
```
78
+
generates the instance
79
+
```scala
80
+
objectPoint:
81
+
...
82
+
givenOrdering[Point] =Ordering.derived
83
+
```
84
+
85
+
86
+
#### `F` and `DerivingType` have parameters of matching kind on the right
87
+
This section covers cases where you can pair arguments of `F` and `DerivingType` starting from the right such that they have the same kinds pairwise, and all arguments of `F` or `DerivingType` (or both) are used up.
88
+
`F` must also have at least one parameter.
89
+
90
+
The general shape will then be:
91
+
```scala
92
+
given [...]:TC[ [...] =>>DerivingType[...] ] =TC.derived
93
+
```
94
+
Where of course `TC` and `DerivingType` are applied to types of the correct kind.
95
+
96
+
To make this work, we split it into 3 cases:
97
+
98
+
If `F` and `DerivingType` take the same number of arguments (`N == K`):
0 commit comments