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
Copy file name to clipboardExpand all lines: docs/docs/reference/contextual-implicit/derivation.md
+17-17Lines changed: 17 additions & 17 deletions
Original file line number
Diff line number
Diff line change
@@ -3,18 +3,18 @@ layout: doc-page
3
3
title: Typeclass Derivation
4
4
---
5
5
6
-
Typeclass derivation is a way to generate instances of certain type classes automatically or with minimal code hints. A type class in this sense is any trait or class with a type parameter that describes the type being operated on. Commonly used examples are `Eql`, `Ordering`, `Show`, or `Pickling`. Example:
6
+
Typeclass derivation is a way to generate implicit instances for certain type classes automatically or with minimal code hints. A type class in this sense is any trait or class with a type parameter that describes the type being operated on. Commonly used examples are `Eql`, `Ordering`, `Show`, or `Pickling`. Example:
7
7
```scala
8
8
enumTree[T] derivesEql, Ordering, Pickling {
9
9
caseBranch(left: Tree[T], right: Tree[T])
10
10
caseLeaf(elem: T)
11
11
}
12
12
```
13
-
The `derives` clause generates implicits for the `Eql`, `Ordering`, and `Pickling` traits in the companion object `Tree`:
13
+
The `derives` clause generates implicit instances for the `Eql`, `Ordering`, and `Pickling` traits in the companion object `Tree`:
@@ -42,8 +42,7 @@ A trait or class can appear in a `derives` clause if its companion object define
42
42
```scala
43
43
defderived[T] givenGeneric[T] = ...
44
44
```
45
-
That is, the `derived` method takes an implicit parameter of type `Generic` that determines the _shape_ of the deriving type `T` and it computes the typeclass implementation according to that shape. Implicits for `Generic` are generated automatically for any type that derives a typeclass with a `derived`
46
-
method that refers to `Generic`. One can also derive `Generic` alone, which means a `Generic` instance is generated without any other type class instances. E.g.:
45
+
That is, the `derived` method takes an implicit parameter of type `Generic` that determines the _shape_ of the deriving type `T` and it computes the typeclass implementation according to that shape. An implicit `Generic` instance is generated automatically for any type that derives a typeclass with a `derived` method that refers to `Generic`. One can also derive `Generic` alone, which means a `Generic` instance is generated without any other type class instances. E.g.:
47
46
```scala
48
47
sealedtraitParseResult[T] derivesGeneric
49
48
```
@@ -94,7 +93,7 @@ is represented as `T *: Unit` since there is no direct syntax for such tuples: `
94
93
95
94
### The Generic Typeclass
96
95
97
-
For every class `C[T_1,...,T_n]` with a `derives` clause, the compiler generates in the companion object of `C` an implicit for `Generic[C[T_1,...,T_n]]` that follows the outline below:
96
+
For every class `C[T_1,...,T_n]` with a `derives` clause, the compiler generates in the companion object of `C` an implicit instance for `Generic[C[T_1,...,T_n]]` that follows the outline below:
We need to implement a method `Eql.derived` that produces an implicit value of type `Eql[T]` provided
218
-
there exists an implicit value of type `Generic[T]`. Here's a possible solution:
216
+
We need to implement a method `Eql.derived` that produces an implicit instance of type `Eql[T]` provided
217
+
there exists an implicit instance of type `Generic[T]`. Here's a possible solution:
219
218
```scala
220
219
inlinedefderived[T] given (ev: Generic[T]):Eql[T] =newEql[T] {
221
220
defeql(x: T, y: T):Boolean= {
@@ -333,21 +332,22 @@ implicit [T] for Eql[Tree[T]] given (elemEq: Eql[T]) {
333
332
}
334
333
```
335
334
336
-
One important difference between this approach and Scala-2 typeclass derivation frameworks such as Shapeless or Magnolia is that no automatic attempt is made to generate typeclass instances of elements recursively using the generic derivation framework. There must be an implicit value of type `Eql[T]` (which can of course be produced in turn using `Eql.derived`), or the compilation will fail. The advantage of this more restrictive approach to typeclass derivation is that it avoids uncontrolled transitive typeclass derivation by design. This keeps code sizes smaller, compile times lower, and is generally more predictable.
335
+
One important difference between this approach and Scala-2 typeclass derivation frameworks such as Shapeless or Magnolia is that no automatic attempt is made to generate typeclass instances of elements recursively using the generic derivation framework. There must be an implicit instance of type `Eql[T]` (which can of course be produced in turn using `Eql.derived`), or the compilation will fail. The advantage of this more restrictive approach to typeclass derivation is that it avoids uncontrolled transitive typeclass derivation by design. This keeps code sizes smaller, compile times lower, and is generally more predictable.
337
336
338
-
### Derived Instances Elsewhere
337
+
### Deriving Instances Elsewhere
339
338
340
339
Sometimes one would like to derive a typeclass instance for an ADT after the ADT is defined, without being able to change the code of the ADT itself.
341
-
To do this, simply define an instance with the `derived` method of the typeclass as right-hand side. E.g, to implement `Ordering` for `Option`, define:
340
+
To do this, simply define an implicit instance with the `derived` method of the typeclass as right-hand side. E.g, to implement `Ordering` for `Option`, define:
Copy file name to clipboardExpand all lines: docs/docs/reference/contextual-implicit/extension-methods.md
+3-7Lines changed: 3 additions & 7 deletions
Original file line number
Diff line number
Diff line change
@@ -36,7 +36,7 @@ When is an extension method applicable? There are two possibilities.
36
36
37
37
- An extension method is applicable if it is visible under a simple name, by being defined
38
38
or inherited or imported in a scope enclosing the application.
39
-
- An extension method is applicable if it is a member of some implicit value at the point of the application.
39
+
- An extension method is applicable if it is a member of some implicit instance at the point of the application.
40
40
41
41
As an example, consider an extension method `longestStrings` on `String` defined in a trait `StringSeqOps`.
42
42
@@ -48,7 +48,7 @@ trait StringSeqOps {
48
48
}
49
49
}
50
50
```
51
-
We can make the extension method available by defining an implicit for `StringSeqOps`, like this:
51
+
We can make the extension method available by defining an implicit instance for `StringSeqOps`, like this:
52
52
```scala
53
53
implicit ops1 forStringSeqOps
54
54
```
@@ -76,7 +76,7 @@ and where `T` is the expected type. The following two rewritings are tried in or
76
76
from `T` to a type containing `m`. If there is more than one way of rewriting, an ambiguity error results.
77
77
78
78
So `circle.circumference` translates to `CircleOps.circumference(circle)`, provided
79
-
`circle` has type `Circle` and `CircleOps` is an eligible implicit value (i.e. it is visible at the point of call or it is defined in the companion object of `Circle`).
79
+
`circle` has type `Circle` and `CircleOps` is an eligible implicit (i.e. it is visible at the point of call or it is defined in the companion object of `Circle`).
80
80
81
81
### Implicits for Extension Methods
82
82
@@ -144,7 +144,3 @@ to the [current syntax](https://github.com/lampepfl/dotty/blob/master/docs/docs/
144
144
DefSig ::= ...
145
145
| ‘(’ DefParam ‘)’ [nl] id [DefTypeParamClause] DefParamClauses
Copy file name to clipboardExpand all lines: docs/docs/reference/contextual-implicit/import-implied.md
+8-6Lines changed: 8 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,7 @@ layout: doc-page
3
3
title: "Import Implicit"
4
4
---
5
5
6
-
A special form of import is used to import implicit values. Example:
6
+
A special form of import is used to import implicit instances. Example:
7
7
```scala
8
8
objectA {
9
9
classTC
@@ -16,16 +16,16 @@ object B {
16
16
}
17
17
```
18
18
In the code above, the `import A._` clause of object `B` will import all members
19
-
of `A`_except_ the implicit `tc`. Conversely, the second import `import implicit A._` will import _only_ that implicit.
19
+
of `A`_except_ the implicit `tc`. Conversely, the second import `import implicit A._` will import _only_ that implicit instance.
20
20
21
-
Generally, a normal import clause brings all members except implicit values into scope whereas an `import implicit` clause brings only implicit values into scope.
21
+
Generally, a normal import clause brings all members except implicit instances into scope whereas an `import implicit` clause brings only implicit instances into scope.
22
22
23
23
There are two main benefits arising from these rules:
24
24
25
-
- It is made clearer where implicit values in scope are coming from. In particular, it is not possible to hide imported implicit values in a long list of regular imports.
26
-
- It enables importing all implicit values
25
+
- It is made clearer where implicit instances in scope are coming from. In particular, it is not possible to hide imported implicit instances in a long list of regular imports.
26
+
- It enables importing all implicit instances
27
27
without importing anything else. This is particularly important since implicit
28
-
values can be anonymous, so the usual recourse of using named imports is not
28
+
instances can be anonymous, so the usual recourse of using named imports is not
29
29
practical.
30
30
31
31
### Migration
@@ -41,6 +41,8 @@ To make gradual migration possible, we adapt the following scheme.
41
41
3. In some version after 3.1, an old-style implicit accessed implicitly through a normal import
42
42
will give a compiler error.
43
43
44
+
New-style implicit instance definitions always need to be imported with `import implicit`.
45
+
44
46
These rules mean that library users can use `import implicit` to access old-style implicits in Scala 3.0,
45
47
and will be gently nudged and then forced to do so in later versions. Libraries can then switch to
46
48
new-style implicit definitions once their user base has migrated.
Copy file name to clipboardExpand all lines: docs/docs/reference/contextual-implicit/inferable-by-name-parameters.md
+2-2Lines changed: 2 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -33,14 +33,14 @@ if this is necessary to prevent an otherwise diverging expansion.
33
33
34
34
The precise steps for synthesizing an argument for a by-name parameter of type `=> T` are as follows.
35
35
36
-
1. Create a new implicit for type `T`:
36
+
1. Create a new implicit instance for type `T`:
37
37
38
38
```scala
39
39
implicit lv forT=???
40
40
```
41
41
where `lv` is an arbitrary fresh name.
42
42
43
-
1. Thisimplicit is not immediately available asa candidate for argument inference (making it immediately available could result in a loop in the synthesized computation). But it becomes available in all nested contexts that look again for an implicit argument to a by-name parameter.
43
+
1. Thisinstance is not immediately available asa candidate implicit (making it immediately available could result in a loop in the synthesized computation). But it becomes available in all nested contexts that look again for an implicit argument to a by-name parameter.
44
44
45
45
1. Ifthis search succeeds with expression `E`, and `E` contains references to the implicit `lv`, replace `E` by
Copy file name to clipboardExpand all lines: docs/docs/reference/contextual-implicit/inferable-params.md
+8-4Lines changed: 8 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -30,12 +30,16 @@ max(List(1, 2, 3), Nil)
30
30
31
31
## Anonymous Implicit Parameters
32
32
33
-
In many situations, the name of an implicit parameter of a method need not be mentioned explicitly at all, since it is only used as a synthesized argument for other implicit parameters. In that case one can avoid defining a parameter name and just provide its type. Example:
33
+
In many situations, the name of an implicit parameter of a method need not be
34
+
mentioned explicitly at all, since it is only used in synthesized arguments for
35
+
other implicit parameters. In that case one can avoid defining a parameter name
36
+
and just provide its type. Example:
34
37
```scala
35
38
defmaximum[T](xs: List[T]) givenOrd[T]:T=
36
39
xs.reduceLeft(max)
37
40
```
38
-
`maximum` takes an implicit parameter of type `Ord` only to pass it on as an implicit argument to `max`. The name of the parameter is left out.
41
+
`maximum` takes an implicit parameter of type `Ord` only to pass it on as a
42
+
synthesized argument to `max`. The name of the parameter is left out.
39
43
40
44
Generally, implicit parameters may be given either as a parameter list `(p_1: T_1, ..., p_n: T_n)`
41
45
or as a sequence of types, separated by commas.
@@ -79,9 +83,9 @@ f("abc").given(ctx)
79
83
f.given(global)("abc").given(ctx)
80
84
```
81
85
82
-
## Summoning an Implicit
86
+
## Summoning Implicit Instances
83
87
84
-
A method `the` in `Predef` returns an implicit instance of a given type. For example, the implicit for `Ord[List[Int]]` is generated by
88
+
A method `the` in `Predef` returns an implicit instance for a given type. For example, the implicit for `Ord[List[Int]]` is generated by
85
89
```scala
86
90
the[Ord[List[Int]]] // reduces to ListOrd given IntOrd
implicitListOrd[T] forOrd[List[T]] given (ord: Ord[T]){
21
+
implicitListOrd[T] forOrd[List[T]] given (ord: Ord[T]){
22
22
defcompare(xs: List[T], ys: List[T]):Int= (xs, ys) match {
23
23
case (Nil, Nil) =>0
24
24
case (Nil, _) =>-1
@@ -30,10 +30,10 @@ implicit ListOrd[T] for Ord[List[T]] given (ord: Ord[T]){
30
30
}
31
31
```
32
32
This code defines a trait `Ord` and two implicit definitions. `IntOrd` defines
33
-
an implicit value of the type `Ord[Int]` whereas `ListOrd[T]` defines implicit values of types`Ord[List[T]]`
34
-
for all types `T` that come with implicit values for `Ord[T]` themselves.
35
-
The `given` clause in `ListOrd` defines an [implicit parameter](./inferable-params.html).
36
-
Given clauses are further explained in the next section.
33
+
an implicit instance of the type `Ord[Int]` whereas `ListOrd[T]` defines implicit instances of type`Ord[List[T]]`
34
+
for all types `T` that come with an implicit instance for `Ord[T]` themselves.
35
+
The `given` clause in `ListOrd` defines an implicit parameter.
36
+
Given clauses are further explained in the [next section](./inferable-params.html).
37
37
38
38
## Anonymous Implicit Instances
39
39
@@ -43,12 +43,12 @@ of the last section can also be expressed like this:
43
43
implicitforOrd[Int] { ... }
44
44
implicit [T] forOrd[List[T]] given (ord: Ord[T]) { ... }
45
45
```
46
-
If the name of an implicit is missing, the compiler will synthesize a name from
46
+
If the name of an implicit instance is missing, the compiler will synthesize a name from
47
47
the type(s) in the `for` clause.
48
48
49
49
## Alias Implicits
50
50
51
-
An alias can be used to define an implicit value that is equal to some expression. E.g.:
51
+
An alias can be used to define an implicit instance that is equal to some expression. E.g.:
52
52
```scala
53
53
implicit global forExecutionContext=newForkJoinPool()
54
54
```
@@ -64,7 +64,7 @@ An alias implicit can have type and context parameters just like any other impli
64
64
65
65
## Implicit Instance Creation
66
66
67
-
An implicit instance without type parameters or given clause is created on-demand, the first time it is accessed. It is not required to ensure safe publication, which means that different threads might create different instances for the same `implicit`clause. If an `implicit` definition has type parameters or a given clause, a fresh instance is created for each reference.
67
+
An implicit instance without type parameters or given clause is created on-demand, the first time it is accessed. It is not required to ensure safe publication, which means that different threads might create different instances for the same `implicit`definition. If an `implicit` definition has type parameters or a given clause, a fresh instance is created for each reference.
Copy file name to clipboardExpand all lines: docs/docs/reference/contextual-implicit/motivation.md
+2-3Lines changed: 2 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -53,14 +53,14 @@ The following pages introduce a redesign of contextual abstractions in Scala. Th
53
53
54
54
3. [ImportImplicit](./import-implied.html) is new form of importthatspecificallyimportsimplicitdefinitionsandnothingelse. New-styleimplicitinstances_mustbe_importedwith`import implicit`, aplainimportwillnolongerbringthemintoscope. Old-styleimplicitdefinitionscanbeimportedwitheitherform.
55
55
56
-
4. [ImplicitConversions](./conversions.html) are now expressed asimplicitvalues of a standard `Conversion` class. All other forms of implicit conversions will be phased out.
56
+
4. [ImplicitConversions](./conversions.html) are now expressed asimplicitinstances of a standard `Conversion` class. All other forms of implicit conversions will be phased out.
57
57
58
58
This section also contains pages describing other language features that are related to context abstraction. Theseare:
59
59
60
60
- [ContextBounds](./context-bounds.html), which carry over unchanged.
61
61
- [ExtensionMethods](./extension-methods.html) replace implicit classes in a way that integrates better with typeclasses.
62
62
- [ImplementingTypeclasses](./typeclasses.html) demonstrates how some common typeclasses can be implemented using the new constructs.
63
-
- [TypeclassDerivation](./derivation.html) introduces constructs to automatically derive typeclassesforADTs.
63
+
- [TypeclassDerivation](./derivation.html) introduces constructs to automatically derive implicit typeclass instancesforADTs.
64
64
- [MultiversalEquality](./multiversal-equality.html) introduces a special typeclass
65
65
to support typesafe equality.
66
66
- [ImplicitFunctionTypes](./query-types.html) introduce a way to abstract over implicit parameterization.
@@ -79,4 +79,3 @@ Could we achieve the same goals by tweaking existing implicits? After having tri
79
79
-Third, even if we would somehow succeed with migration, we still have the problem
80
80
how to teach this. We cannot make existing tutorials go away. Almost all existing tutorials start withimplicit conversions, which will go away; they use normal imports, which will go away, and they explain calls to methods withimplicit parameters by expanding them to plain applications, which will also go away. This means that we'd have
81
81
to add modifications and qualifications to all existing literature and courseware, likely causing more confusion with beginners instead of less. By contrast, with a new syntax there is a clear criterion: Any book or courseware that mentions `implicit` is outdated and should be updated.
0 commit comments