Skip to content

Commit 25d4ede

Browse files
committed
WIP derivation changes
1 parent d79382c commit 25d4ede

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

docs/_docs/reference/contextual/derivation.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,68 @@ given [T: Show] : Show[Tree[T]] = Show.derived
2626

2727
We say that `Tree` is the _deriving type_ and that the `Eq`, `Ordering` and `Show` instances are _derived instances_.
2828

29+
## Exact mechanism
30+
More formally, for a class/trait/object/enum `DerivingType[T_1, ..., T_N] derives TC` (if `DerivingType` does not take parameters, we define `N = 0`), a derived instance is created in `DerivingType`'s companion object (or `DerivingType` itself if it is an object)
31+
32+
What the derived instance looks like depends on the specifics of `DerivingType` and `TC`, first the arity of `TC`:
33+
34+
### `TC` takes 1 parameter
35+
36+
Therefore `TC` is defined as `TC[F[A_1, ..., A_K]]` (`TC[F]` if `K == 0`), there are two further cases depending on the `A_i`s:
37+
38+
#### `F` and all arguments of `DerivingType` have kind `*`
39+
40+
The generated instance is then:
41+
```scala
42+
given [T_1: TC, ..., T_N: TC]: TC[DerivingType[T_1, ..., T_N]] = TC.derived
43+
```
44+
45+
If `N == 0`, we understand the above to mean:
46+
```scala
47+
given TC[DerivingType] = TC.derived
48+
```
49+
50+
<!-- #### You can pair arguments of `F` and `DerivingType` starting from the right such that they have the same kinds pairwise, and all arguments of at least one of them are used up -->
51+
#### `F` and `DerivingType` have their `m` rightmost arguments which have the same kind pairwise and `N >= 0`, `K > 0`, and `m == N` and/or `m == K`
52+
53+
The generated instance is then:
54+
If `m == N == K`:
55+
```scala
56+
given TC[DerivingType] = TC.derived
57+
```
58+
If `m == N < K`:
59+
```scala
60+
given TC[[A_1, ..., A_K] =>> DerivingType[A_(K-N+1), ..., A_K]] = TC.derived
61+
```
62+
63+
TODO: Speak about `N == 0` being allowed, since then `(K-N+1) > K`
64+
65+
If `m == K < N`:
66+
```scala
67+
given [T_1, ... T_(N-K)]: TC[[A_1, ..., A_K] =>> DerivingType[T_1, ... T_(N-K), A_1, ..., A_K]] = TC.derived
68+
```
69+
70+
### `TC` takes 2 parameters
71+
72+
Is `TC` the `CanEqual` type class ?
73+
If yes, proceed as follows, otherwise go to [`TC` is not valid for automatic derivation](#tc-is-not-valid-for-automatic-derivation)
74+
75+
We have therefore: `DerivingType[T_1, ..., T_N] derives CanEqual`
76+
77+
TODO: Talk about higher kinded types
78+
79+
And the generated instance is:
80+
```scala
81+
given [T_1L, T_1R, ..., T_NL, T_NR]
82+
(using CanEqual[T_1L, T_1R], ..., CanEqual[T_NL, T_NR]):
83+
CanEqual[DerivingType[T_1L, ..., T_NL], DerivingType[T_1R, ..., T_NR]] =
84+
CanEqual.derived
85+
```
86+
87+
### `TC` is not valid for automatic derivation
88+
89+
Throw some error.
90+
<!--
2991
More formally, for a class/trait/object/enum `DerivingType derives TC`, the following given instance is created in `DerivingType`'s companion object (or `DerivingType` itself if it is an object):
3092
* if `DerivingType` doesn't have type parameters
3193
```scala
@@ -35,6 +97,7 @@ given TC[DerivingType] = TC.derived
3597
```scala
3698
given [T_1: TC, ... T_N: TC]: TC[DerivingType[T_1, ..., T_N]] = TC.derived
3799
```
100+
-->
38101

39102
`TC.derived` should be an expression that conforms to the expected type `TC[DerivingType]`, potentially elaborated using term and/or type inference.
40103

0 commit comments

Comments
 (0)