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/context-bounds.md
+2-2
Original file line number
Diff line number
Diff line change
@@ -5,11 +5,11 @@ title: "Context Bounds"
5
5
6
6
## Context Bounds
7
7
8
-
A context bound is a shorthand for expressing a common pattern of implicit parameters. For example, the `maximum` function of the last section could also have been written like this:
8
+
A context bound is a shorthand for expressing a common pattern of an inferable parameter that depends on a type parameter. Using a context bound, the `maximum` function of the last section can be written like this:
A bound `: C` on a type parameter `T` of a method or class indicates an inferred parameter `given C[T]`. The inferred parameter(s) generated from context bounds come last in the definition of the containing method or class. E.g.,
12
+
A bound like `: Ord` on a type parameter `T` of a method or class indicates an inferred parameter `given Ord[T]`. The inferred parameter(s) generated from context bounds come last in the definition of the containing method or class. E.g.,
13
13
```
14
14
def f[T: C1 : C2, U: C3](x: T) given (y: U, z: V): R
2. The "magnet" pattern is sometimes used to express many variants of a method. Instead of defining overloaded versions of the method, one can also let the method take one or more arguments of specially defined "magnet" types, into which various argument types can be converted. E.g.
42
+
```scala
43
+
objectCompletions {
44
+
45
+
// The argument "magnet" type
46
+
enumCompletionArg {
47
+
caseError(s: String)
48
+
caseResponse(f: Future[HttpResponse])
49
+
caseStatus(code: Future[StatusCode])
50
+
}
51
+
objectCompletionArg {
52
+
53
+
// conversions defining the possible arguments to pass to `complete`
54
+
// these always come with CompletionArg
55
+
// They can be invoked explicitly, e.g.
56
+
//
57
+
// CompletionArg.from(statusCode)
58
+
59
+
implied from forConversion[String, CompletionArg] {
60
+
defapply(s: String) =CompletionArg.Error(s)
61
+
}
62
+
implied from forConversion[Future[HttpResponse], CompletionArg] {
This setup is more complicated than simple overloading of `complete`, but it can still be useful if normal overloading is not available (as in the case above, since we cannot have two overloaded methods that take `Future[...]` arguments), or if normal overloading would lead to a combinatorial explosion of variants.
@@ -47,7 +47,7 @@ These two conditions ensure that the synthesized derived instances for the trait
47
47
```scala
48
48
defderived[T] withGeneric[T] = ...
49
49
```
50
-
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. A `Generic` instance is generated automatically
50
+
That is, the `derived` method takes an inferable parameter of type `Generic` that determines the _shape_ of the deriving type `T` and it computes the typeclass implementation according to that shape. A `Generic` instance is generated automatically
51
51
for any types that derives a typeclass that needs it. One can also derive `Generic` alone, which means a `Generic` instance is generated without any other type class instances. E.g.:
52
52
```scala
53
53
sealedtraitParseResult[T] derivesGeneric
@@ -99,10 +99,10 @@ is represented as `T *: Unit` since there is no direct syntax for such tuples: `
99
99
100
100
### The Generic TypeClass
101
101
102
-
For every class `C[T_1,...,T_n]` with a `derives` clause, the compiler generates in the companion object of `C` an inferred instance of `Generic[C[T_1,...,T_n]]` that follows
102
+
For every class `C[T_1,...,T_n]` with a `derives` clause, the compiler generates in the companion object of `C` an implied instance of `Generic[C[T_1,...,T_n]]` that follows
@@ -311,7 +311,7 @@ The last, and in a sense most interesting part of the derivation is the comparis
311
311
error("No `Eq` instance was found for $T")
312
312
}
313
313
```
314
-
`tryEql` is an inline method that takes an element type `T` and two element values of that type as arguments. It is defined using an `inline match` that tries to find an implicit instance of `Eq[T]`. If an instance `ev` is found, it proceeds by comparing the arguments using `ev.eql`. On the other hand, if no instance is found
314
+
`tryEql` is an inline method that takes an element type `T` and two element values of that type as arguments. It is defined using an `implicit match` that tries to find an implied instance of `Eq[T]`. If an instance `ev` is found, it proceeds by comparing the arguments using `ev.eql`. On the other hand, if no instance is found
315
315
this signals a compilation error: the user tried a generic derivation of `Eq` for a class with an element type that does not support an `Eq` instance itself. The error is signaled by
316
316
calling the `error` method defined in `scala.compiletime`.
317
317
@@ -320,7 +320,7 @@ calling the `error` method defined in `scala.compiletime`.
320
320
**Example:** Here is a slightly polished and compacted version of the code that's generated by inline expansion for the derived `Eq` instance of class `Tree`.
321
321
322
322
```scala
323
-
inferred [T] with (elemEq: Eq[T]) forEq[Tree[T]] {
323
+
implied [T] with (elemEq: Eq[T]) forEq[Tree[T]] {
324
324
defeql(x: Tree[T], y: Tree[T]):Boolean= {
325
325
valev= infer[Generic[Tree[T]]]
326
326
valmx= ev.reflect(x)
@@ -339,21 +339,21 @@ inferred [T] with (elemEq: Eq[T]) for Eq[Tree[T]] {
339
339
}
340
340
```
341
341
342
-
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 `Eq[T]` (which can of course be produced in turn using `Eq.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.
342
+
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 implied instance of `Eq[T]` (which can of course be produced in turn using `Eq.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.
343
343
344
344
### Derived Instances Elsewhere
345
345
346
346
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.
347
347
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:
Copy file name to clipboardExpand all lines: docs/docs/reference/contextual/extension-methods.md
+7-8
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 an eligible implicit value at the point of the application.
39
+
- An extension method is applicable if it is a member of some implied 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,16 +48,15 @@ trait StringSeqOps {
48
48
}
49
49
}
50
50
```
51
-
We can make the extension method available by defining an implicit instance of `StringSeqOps`, like this:
51
+
We can make the extension method available by defining an implied instance of `StringSeqOps`, like this:
52
52
```scala
53
-
instance StringSeqOps1 ofStringSeqOps
53
+
implied ops1 forStringSeqOps
54
54
```
55
55
Then
56
56
```scala
57
57
List("here", "is", "a", "list").longestStrings
58
58
```
59
-
is legal everywhere `StringSeqOps1` is available as an implicit value. Alternatively, we can define `longestStrings`
60
-
as a member of a normal object. But then the method has to be brought into scope to be usable as an extension method.
59
+
is legal everywhere `ops1` is available as an implied instance. Alternatively, we can define `longestStrings` as a member of a normal object. But then the method has to be brought into scope to be usable as an extension method.
61
60
62
61
```scala
63
62
objectops2extendsStringSeqOps
@@ -70,14 +69,14 @@ Assume a selection `e.m[Ts]` where `m` is not a member of `e`, where the type ar
70
69
and where `T` is the expected type. The following two rewritings are tried in order:
71
70
72
71
1. The selection is rewritten to `m[Ts](e)`.
73
-
2. If the first rewriting does not typecheck with expected type `T`, and there is an implicit value`i`
74
-
in either the current scope or in the implicit scope of `T`, and `i` defines an extension
72
+
2. If the first rewriting does not typecheck with expected type `T`, and there is an implied instance`i`
73
+
in either the current scope or in the implied scope of `T`, and `i` defines an extension
75
74
method named `m`, then selection is expanded to `i.m[Ts](e)`.
76
75
This second rewriting is attempted at the time where the compiler also tries an implicit conversion
77
76
from `T` to a type containing `m`. If there is more than one way of rewriting, an ambiguity error results.
78
77
79
78
So `circle.circumference` translates to `CircleOps.circumference(circle)`, provided
80
-
`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`).
79
+
`circle` has type `Circle` and `CircleOps` is an eligible implied instance (i.e. it is visible at the point of call or it is defined in the companion object of `Circle`).
0 commit comments