Skip to content

Commit b626dc9

Browse files
committed
Updates to contextual/* docs
1 parent 67fcf92 commit b626dc9

14 files changed

+178
-155
lines changed

docs/docs/reference/contextual/context-bounds.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ title: "Context Bounds"
55

66
## Context Bounds
77

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:
8+
A context bound is a shorthand for expressing a common pattern of a context parameter that depends on a type parameter. Using a context bound, the `maximum` function of the last section can be written like this:
99
```scala
1010
def maximum[T: Ord](xs: List[T]): T = xs.reduceLeft(max)
1111
```
12-
A bound like `: Ord` on a type parameter `T` of a method or class indicates an inferable parameter `given Ord[T]`. The inferable 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 a context parameter `given Ord[T]`. The context parameter(s) generated from context bounds come last in the definition of the containing method or class. E.g.,
1313
```scala
1414
def f[T: C1 : C2, U: C3](x: T) given (y: U, z: V): R
1515
```

docs/docs/reference/contextual/conversions.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ implied for Conversion[String, Token] {
1414
def apply(str: String): Token = new KeyWord(str)
1515
}
1616
```
17-
Using an implied alias this can be expressed more concisely as:
17+
Using an implied alias instance this can be expressed more concisely as:
1818
```scala
1919
implied for Conversion[String, Token] = new KeyWord(_)
2020
```
@@ -25,7 +25,7 @@ An implicit conversion is applied automatically by the compiler in three situati
2525
3. In an application `e.m(args)` with `e` of type `T`, if `T` does define
2626
some member(s) named `m`, but none of these members can be applied to the arguments `args`.
2727

28-
In the first case, the compiler looks in the implied scope for a an instance of
28+
In the first case, the compiler looks for an implied instance of
2929
`scala.Conversion` that maps an argument of type `T` to type `S`. In the second and third
3030
case, it looks for an instance of `scala.Conversion` that maps an argument of type `T`
3131
to a type that defines a member `m` which can be applied to `args` if present.
@@ -59,9 +59,9 @@ object Completions {
5959
//
6060
// CompletionArg.fromStatusCode(statusCode)
6161

62-
implied fromString for Conversion[String, CompletionArg] = Error(_)
63-
implied fromFuture for Conversion[Future[HttpResponse], CompletionArg] = Response(_)
64-
implied fromStatusCode for Conversion[Future[StatusCode], CompletionArg] = Status(_)
62+
implied fromString for Conversion[String, CompletionArg] = Error(_)
63+
implied fromFuture for Conversion[Future[HttpResponse], CompletionArg] = Response(_)
64+
implied fromStatusCode for Conversion[Future[StatusCode], CompletionArg] = Status(_)
6565
}
6666
import CompletionArg._
6767

docs/docs/reference/contextual/derivation.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ layout: doc-page
33
title: Typeclass Derivation
44
---
55

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 implied 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:
77
```scala
88
enum Tree[T] derives Eql, Ordering, Pickling {
99
case Branch(left: Tree[T], right: Tree[T])
@@ -12,14 +12,14 @@ enum Tree[T] derives Eql, Ordering, Pickling {
1212
```
1313
The `derives` clause generates implied instances of the `Eql`, `Ordering`, and `Pickling` traits in the companion object `Tree`:
1414
```scala
15-
implied [T: Eql] for Eql[Tree[T]] = Eql.derived
16-
implied [T: Ordering] for Ordering[Tree[T]] = Ordering.derived
17-
implied [T: Pickling] for Pickling[Tree[T]] = Pickling.derived
15+
implied [T: Eql] for Eql[Tree[T]] = Eql.derived
16+
implied [T: Ordering] for Ordering[Tree[T]] = Ordering.derived
17+
implied [T: Pickling] for Pickling[Tree[T]] = Pickling.derived
1818
```
1919

2020
### Deriving Types
2121

22-
Besides for `enums`, typeclasses can also be derived for other sets of classes and objects that form an algebraic data type. These are:
22+
Besides for enums, typeclasses can also be derived for other sets of classes and objects that form an algebraic data type. These are:
2323

2424
- individual case classes or case objects
2525
- sealed classes or traits that have only case classes and case objects as children.
@@ -42,7 +42,7 @@ A trait or class can appear in a `derives` clause if its companion object define
4242
```scala
4343
def derived[T] given Generic[T] = ...
4444
```
45-
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. An implied `Generic` instance is generated automatically for any type that derives a typeclass with a `derived`
45+
That is, the `derived` method takes a context parameter of type `Generic` that determines the _shape_ of the deriving type `T` and it computes the typeclass implementation according to that shape. An implied `Generic` instance is generated automatically for any type that derives a typeclass with a `derived`
4646
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.:
4747
```scala
4848
sealed trait ParseResult[T] derives Generic
@@ -142,15 +142,15 @@ abstract class Generic[T] {
142142
```
143143
It defines the `Shape` type for the ADT `T`, as well as two methods that map between a
144144
type `T` and a generic representation of `T`, which we call a `Mirror`:
145-
The `reflect` method maps an instance value of the ADT `T` to its mirror whereas
145+
The `reflect` method maps an instance of the ADT `T` to its mirror whereas
146146
the `reify` method goes the other way. There's also a `common` method that returns
147147
a value of type `GenericClass` which contains information that is the same for all
148148
instances of a class (right now, this consists of the runtime `Class` value and
149149
the names of the cases and their parameters).
150150

151151
### Mirrors
152152

153-
A mirror is a generic representation of an instance value of an ADT. `Mirror` objects have three components:
153+
A mirror is a generic representation of an instance of an ADT. `Mirror` objects have three components:
154154

155155
- `adtClass: GenericClass`: The representation of the ADT class
156156
- `ordinal: Int`: The ordinal number of the case among all cases of the ADT, starting from 0
@@ -208,15 +208,15 @@ a mirror over that array, and finally uses the `reify` method in `Reflected` to
208208

209209
### How to Write Generic Typeclasses
210210

211-
Based on the machinery developed so far it becomes possible to define type classes generically. This means that the `derived` method will compute a type class instance for any ADT that has a `Generic` instance, recursively.
211+
Based on the machinery developed so far it becomes possible to define type classes generically. This means that the `derived` method will compute a type class instance for any ADT that has an implied `Generic` instance, recursively.
212212
The implementation of these methods typically uses three new type-level constructs in Dotty: inline methods, inline matches, and implicit matches. As an example, here is one possible implementation of a generic `Eql` type class, with explanations. Let's assume `Eql` is defined by the following trait:
213213
```scala
214214
trait Eql[T] {
215215
def eql(x: T, y: T): Boolean
216216
}
217217
```
218-
We need to implement a method `Eql.derived` that produces an instance of `Eql[T]` provided
219-
there exists evidence of type `Generic[T]`. Here's a possible solution:
218+
We need to implement a method `Eql.derived` that produces an instance for `Eql[T]` provided
219+
there exists an implied instance for `Generic[T]`. Here's a possible solution:
220220
```scala
221221
inline def derived[T] given (ev: Generic[T]): Eql[T] = new Eql[T] {
222222
def eql(x: T, y: T): Boolean = {
@@ -307,15 +307,15 @@ The last, and in a sense most interesting part of the derivation is the comparis
307307
}
308308
```
309309
`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 `Eql[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
310-
this signals a compilation error: the user tried a generic derivation of `Eql` for a class with an element type that does not support an `Eql` instance itself. The error is signaled by
310+
this signals a compilation error: the user tried a generic derivation of `Eql` for a class with an element type that does not have an `Eql` instance itself. The error is signaled by
311311
calling the `error` method defined in `scala.compiletime`.
312312

313313
**Note:** At the moment our error diagnostics for metaprogramming does not support yet interpolated string arguments for the `scala.compiletime.error` method that is called in the second case above. As an alternative, one can simply leave off the second case, then a missing typeclass would result in a "failure to reduce match" error.
314314

315315
**Example:** Here is a slightly polished and compacted version of the code that's generated by inline expansion for the derived `Eql` instance of class `Tree`.
316316

317317
```scala
318-
implied [T] given (elemEq: Eql[T]) for Eql[Tree[T]] {
318+
implied [T] for Eql[Tree[T]] given (elemEq: Eql[T]) {
319319
def eql(x: Tree[T], y: Tree[T]): Boolean = {
320320
val ev = the[Generic[Tree[T]]]
321321
val mx = ev.reflect(x)
@@ -336,14 +336,14 @@ implied [T] given (elemEq: Eql[T]) for Eql[Tree[T]] {
336336

337337
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 `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.
338338

339-
### Derived Instances Elsewhere
339+
### Deriving Instances Elsewhere
340340

341341
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.
342342
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:
343343
```scala
344-
implied [T: Ordering]: Ordering[Option[T]] = Ordering.derived
344+
implied [T: Ordering] for Ordering[Option[T]] = Ordering.derived
345345
```
346-
Usually, the `Ordering.derived` clause has an inferable parameter of type
346+
Usually, the `Ordering.derived` clause has a context parameter of type
347347
`Generic[Option[T]]`. Since the `Option` trait has a `derives` clause,
348348
the necessary implied instance is already present in the companion object of `Option`.
349349
If the ADT in question does not have a `derives` clause, an implied `Generic` instance

docs/docs/reference/contextual/extension-methods.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ implied StringOps {
9090
}
9191
}
9292

93-
implied ListOps {
93+
implied {
9494
def (xs: List[T]) second[T] = xs.tail.head
9595
}
9696
```
97-
If such implied instances are anonymous (as in the examples above), their name is synthesized from the name
97+
If such a representative is anonymous (as in the second clause above), its name is synthesized from the name
9898
of the first defined extension method.
9999

100100
### Operators
@@ -144,7 +144,3 @@ to the [current syntax](https://github.com/lampepfl/dotty/blob/master/docs/docs/
144144
DefSig ::= ...
145145
| ‘(’ DefParam ‘)’ [nl] id [DefTypeParamClause] DefParamClauses
146146
```
147-
148-
149-
150-

docs/docs/reference/contextual/import-implied.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
layout: doc-page
3-
title: "Implied Imports"
3+
title: "Importing Implied Instances"
44
---
55

66
A special form of import is used to import implied instances. Example:
@@ -18,7 +18,7 @@ object B {
1818
In the code above, the `import A._` clause of object `B` will import all members
1919
of `A` _except_ the implied instance `tc`. Conversely, the second import `import implied A._` will import _only_ that implied instance.
2020

21-
Generally, a normal import clause brings all definitions except implied instances into scope whereas an `import implied` clause brings only implied instances into scope.
21+
Generally, a normal import clause brings all members except implied instances into scope whereas an `import implied` clause brings only implied instances into scope.
2222

2323
There are two main benefits arising from these rules:
2424

@@ -28,22 +28,22 @@ There are two main benefits arising from these rules:
2828
instances can be anonymous, so the usual recourse of using named imports is not
2929
practical.
3030

31-
### Relationship with Old-Style Implicits
31+
### Migration
3232

33-
The rules of implied imports above have the consequence that a library
33+
The rules for `import implied` above have the consequence that a library
3434
would have to migrate in lockstep with all its users from old style implicits and
3535
normal imports to implied instances and imports.
3636

3737
The following modifications avoid this hurdle to migration.
3838

39-
1. An implied import also brings old style implicits into scope. So, in Scala 3.0
40-
an old-style implicit definition can be brought into scope either by a normal or
41-
by an implied import.
39+
1. An `import implied` also brings old style implicits into scope. So, in Scala 3.0
40+
an old-style implicit definition can be brought into scope either by a normal import or
41+
by an `import implied`.
4242

43-
2. In Scala 3.1, an old-style implicits accessed implicitly through a normal import
43+
2. In Scala 3.1, old-style implicits accessed through a normal import
4444
will give a deprecation warning.
4545

46-
3. In some version after 3.1, an old-style implicits accessed implicitly through a normal import
46+
3. In some version after 3.1, an old-style implicit accessed through a normal import
4747
will give a compiler error.
4848

4949
These rules mean that library users can use `import implied` to access old-style implicits in Scala 3.0,

docs/docs/reference/contextual/inferable-by-name-parameters.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
22
layout: doc-page
3-
title: "Inferable By-Name Parameters"
3+
title: "By-Name Context Parameters"
44
---
55

6-
Inferable by-name parameters can be used to avoid a divergent inferred expansion. Example:
6+
Context parameters can be declared by-name to avoid a divergent inferred expansion. Example:
77

88
```scala
99
trait Codec[T] {
@@ -12,7 +12,7 @@ trait Codec[T] {
1212

1313
implied intCodec for Codec[Int] = ???
1414

15-
implied optionCodec[T] given (ev: => Codec[T]) for Codec[Option[T]] {
15+
implied optionCodec[T] for Codec[Option[T]] given (ev: => Codec[T]) {
1616
def write(xo: Option[T]) = xo match {
1717
case Some(x) => ev.write(x)
1818
case None =>
@@ -24,14 +24,14 @@ val s = the[Codec[Option[Int]]]
2424
s.write(Some(33))
2525
s.write(None)
2626
```
27-
As is the case for a normal by-name parameter, the argument for the inferable parameter `ev`
27+
As is the case for a normal by-name parameter, the argument for the context parameter `ev`
2828
is evaluated on demand. In the example above, if the option value `x` is `None`, it is
2929
not evaluated at all.
3030

31-
The synthesized argument for an inferable parameter is backed by a local val
31+
The synthesized argument for a context parameter is backed by a local val
3232
if this is necessary to prevent an otherwise diverging expansion.
3333

34-
The precise steps for constructing an inferable argument for a by-name parameter of type `=> T` are as follows.
34+
The precise steps for synthesizing an argument for a by-name context parameter of type `=> T` are as follows.
3535

3636
1. Create a new implied instance of type `T`:
3737

0 commit comments

Comments
 (0)