From 0182028e5f628140c3c33069e937d06770f7838b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 25 Apr 2019 23:12:26 +0200 Subject: [PATCH] More fixes to contextual-implicit These were not merged by accident before. --- .../contextual-implicit/import-implied.md | 32 +++++++++---------- .../inferable-by-name-parameters.md | 12 +++---- .../contextual-implicit/inferable-params.md | 22 ++++++------- .../contextual-implicit/typeclasses.md | 12 +++---- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/docs/docs/reference/contextual-implicit/import-implied.md b/docs/docs/reference/contextual-implicit/import-implied.md index ff044cee7b67..e0b3130a889f 100644 --- a/docs/docs/reference/contextual-implicit/import-implied.md +++ b/docs/docs/reference/contextual-implicit/import-implied.md @@ -1,44 +1,44 @@ --- layout: doc-page -title: "Evidence Imports" +title: "Import Implicit" --- -A special form of import is used to import evidence values. Example: +A special form of import is used to import implicit values. Example: ```scala object A { class TC - evidence tc for TC + implicit tc for TC def f given TC = ??? } object B { import A._ - import evidence A._ + import implicit A._ } ``` In the code above, the `import A._` clause of object `B` will import all members -of `A` _except_ the evidence `tc`. Conversely, the second import `import evidence A._` will import _only_ that evidence. +of `A` _except_ the implicit `tc`. Conversely, the second import `import implicit A._` will import _only_ that implicit. -Generally, a normal import clause brings all members except evidence values into scope whereas an `import evidence` clause brings only evidence values into scope. +Generally, a normal import clause brings all members except implicit values into scope whereas an `import implicit` clause brings only implicit values into scope. There are two main benefits arising from these rules: - - It is made clearer where evidence values in scope are coming from. In particular, it is not possible to hide imported evidence values in a long list of regular imports. - - It enables importing all evidence values - without importing anything else. This is particularly important since evidence + - 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. + - It enables importing all implicit values + without importing anything else. This is particularly important since implicit values can be anonymous, so the usual recourse of using named imports is not practical. ### Relationship with Old-Style Implicits -The rules of evidence imports above have the consequence that a library +The rules of "import implicit" above have the consequence that a library would have to migrate in lockstep with all its users from old style implicit definitions and -normal imports to evidence definitions and evidence imports. +normal imports to new style implicit definitions and `import implicit`. The following modifications avoid this hurdle to migration. - 1. An evidence import also brings old style implicits into scope. So, in Scala 3.0 - an old-style implicit definition can be brought into scope either by a normal or - by an evidence import. + 1. An `import implicit` also brings old style implicits into scope. So, in Scala 3.0 + an old-style implicit definition can be brought into scope either by a normal import + or by an `import implicit`. 2. In Scala 3.1, an old-style implicits accessed implicitly through a normal import will give a deprecation warning. @@ -46,6 +46,6 @@ The following modifications avoid this hurdle to migration. 3. In some version after 3.1, an old-style implicits accessed implicitly through a normal import will give a compiler error. -These rules mean that library users can use `import evidence` to access old-style implicits in Scala 3.0, +These rules mean that library users can use `import implicit` to access old-style implicits in Scala 3.0, and will be gently nudged and then forced to do so in later versions. Libraries can then switch to -evidence definitions once their user base has migrated. +new-style implicit definitions once their user base has migrated. diff --git a/docs/docs/reference/contextual-implicit/inferable-by-name-parameters.md b/docs/docs/reference/contextual-implicit/inferable-by-name-parameters.md index 040a1d92de01..80ae11b04b4c 100644 --- a/docs/docs/reference/contextual-implicit/inferable-by-name-parameters.md +++ b/docs/docs/reference/contextual-implicit/inferable-by-name-parameters.md @@ -10,9 +10,9 @@ trait Codec[T] { def write(x: T): Unit } -evidence intCodec for Codec[Int] = ??? +implicit intCodec for Codec[Int] = ??? -evidence optionCodec[T] given (ev: => Codec[T]) for Codec[Option[T]] { +implicit optionCodec[T] given (ev: => Codec[T]) for Codec[Option[T]] { def write(xo: Option[T]) = xo match { case Some(x) => ev.write(x) case None => @@ -33,20 +33,20 @@ if this is necessary to prevent an otherwise diverging expansion. The precise steps for constructing an inferable argument for a by-name parameter of type `=> T` are as follows. - 1. Create a new evidence value of type `T`: + 1. Create a new implicit value of type `T`: ```scala - evidence lv for T = ??? + implicit lv for T = ??? ``` where `lv` is an arbitrary fresh name. 1. This instance is not immediately available as 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 inferred argument to a by-name parameter. - 1. If this search succeeds with expression `E`, and `E` contains references to the evidence `lv`, replace `E` by + 1. If this search succeeds with expression `E`, and `E` contains references to the implicit `lv`, replace `E` by ```scala - { evidence lv for T = E; lv } + { implicit lv for T = E; lv } ``` Otherwise, return `E` unchanged. diff --git a/docs/docs/reference/contextual-implicit/inferable-params.md b/docs/docs/reference/contextual-implicit/inferable-params.md index 2e71d5412bc5..b7384e5d69ed 100644 --- a/docs/docs/reference/contextual-implicit/inferable-params.md +++ b/docs/docs/reference/contextual-implicit/inferable-params.md @@ -9,13 +9,13 @@ call trees where the same value is passed over and over again in long call chain functions. Given clauses can help here since they enable the compiler to synthesize repetitive arguments instead of the programmer having to write them explicitly. -For example, given the [evidence definitions](./instance-defs.md) of the previous section, +For example, given the [implicit instances](./instance-defs.md) of the previous section, a maximum function that works for any arguments for which an ordering exists can be defined as follows: ```scala def max[T](x: T, y: T) given (ord: Ord[T]): T = if (ord.compare(x, y) < 1) y else x ``` -Here, the part following `given` introduces a constraint that `T` is ordered, or, otherwise put, that evidence for `Ord[T]` exists. The evidence is passed as an _implicit parameter_ to the method. Inside the method, the evidence value can be accessed under the name `ord`. +Here, the part following `given` introduces a constraint that `T` is ordered, or, otherwise put, that evidence for `Ord[T]` exists. The evidence is passed as an _implicit parameter_ to the method. Inside the method, the implicit value can be accessed under the name `ord`. The `max` method can be applied as follows: ```scala @@ -29,14 +29,14 @@ max(List(1, 2, 3), Nil) ## Anonymous Inferable Parameters -In many situations, the name of an evidence parameter of a method need not be mentioned explicitly at all, since it is only used as synthesized evidence for other constraints. In that case one can avoid defining a parameter name and just provide its type. Example: +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 synthesized implicit for other constraints. In that case one can avoid defining a parameter name and just provide its type. Example: ```scala def maximum[T](xs: List[T]) given Ord[T]: T = xs.reduceLeft(max) ``` -`maximum` takes an evidence parameter of type `Ord` only to pass it on as an implicit argument to `max`. The name of the parameter is left out. +`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. -Generally, evidence parameters may be given either as a parameter list `(p_1: T_1, ..., p_n: T_n)` or as a sequence of types, separated by commas. +Generally, implicit parameters may be given either as a parameter list `(p_1: T_1, ..., p_n: T_n)` or as a sequence of types, separated by commas. ## Inferring Complex Arguments @@ -66,8 +66,8 @@ There can be several inferable parameter lists in a definition. Example: ```scala def f given (u: Universe) (x: u.T) given Context = ... -evidence global for Universe { type T = String ... } -evidence ctx for Context { ... } +implicit global for Universe { type T = String ... } +implicit ctx for Context { ... } ``` Then the following calls are all valid (and normalize to the last one) ```scala @@ -77,17 +77,17 @@ f("abc") given ctx (f given global)("abc") given ctx ``` -## Summoning the Evidence +## Summoning an Implicit -A method `the` in `Predef` summons the evidence for a given type. For example, the evidence for `Ord[List[Int]]` is generated by +A method `the` in `Predef` summons an implicit for a given type. For example, the implicit for `Ord[List[Int]]` is generated by ```scala the[Ord[List[Int]]] // reduces to ListOrd given IntOrd ``` -The `the` method is simply defined as the (non-widening) identity function over an evidence parameter. +The `the` method is simply defined as the (non-widening) identity function over an implicit parameter. ```scala def the[T] given (x: T): x.type = x ``` -Functions like `the` that have only evidence parameters are also called _context queries_. +Functions like `the` that have only implicit parameters are also called _context queries_. ## Syntax diff --git a/docs/docs/reference/contextual-implicit/typeclasses.md b/docs/docs/reference/contextual-implicit/typeclasses.md index 3f5b49e84962..e1fdc9bc57a7 100644 --- a/docs/docs/reference/contextual-implicit/typeclasses.md +++ b/docs/docs/reference/contextual-implicit/typeclasses.md @@ -3,9 +3,9 @@ layout: doc-page title: "Implementing Typeclasses" --- -Evidence definitions, extension methods and context bounds +Implicit instances, extension methods and context bounds allow a concise and natural expression of _typeclasses_. Typeclasses are just traits -with canonical implementations defined by evidence definitions. Here are some examples of standard typeclasses: +with canonical implementations defined by implicit instances. Here are some examples of standard typeclasses: ### Semigroups and monoids: @@ -20,12 +20,12 @@ object Monoid { def apply[T] given Monoid[T] = the[Monoid[T]] } -evidence for Monoid[String] { +implicit for Monoid[String] { def (x: String) combine (y: String): String = x.concat(y) def unit: String = "" } -evidence for Monoid[Int] { +implicit for Monoid[Int] { def (x: Int) combine (y: Int): Int = x + y def unit: Int = 0 } @@ -48,14 +48,14 @@ trait Monad[F[_]] extends Functor[F] { def pure[A](x: A): F[A] } -evidence ListMonad for Monad[List] { +implicit ListMonad for Monad[List] { def (xs: List[A]) flatMap [A, B] (f: A => List[B]): List[B] = xs.flatMap(f) def pure[A](x: A): List[A] = List(x) } -evidence ReaderMonad[Ctx] for Monad[[X] => Ctx => X] { +implicit ReaderMonad[Ctx] for Monad[[X] => Ctx => X] { def (r: Ctx => A) flatMap [A, B] (f: A => Ctx => B): Ctx => B = ctx => f(r(ctx))(ctx) def pure[A](x: A): Ctx => A =