8000 Merge pull request #1018 from martijnhoekstra/patch-3 · nanarth/docs.scala-lang@6a15f7b · GitHub
[go: up one dir, main page]

Skip to content

Commit 6a15f7b

Browse files
authored
Merge pull request scala#1018 from martijnhoekstra/patch-3
Try to clarify implicit parameters tour
2 parents c623933 + a8ecdb4 commit 6a15f7b

File tree

1 file changed

+28
-20
lines changed

1 file changed

+28
-20
lines changed

_tour/implicit-parameters.md

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line cha 10000 nge
@@ -13,52 +13,60 @@ previous-page: self-types
1313
redirect_from: "/tutorials/tour/implicit-parameters.html"
1414
---
1515

16-
A method with _implicit parameters_ can be applied to arguments just like a normal method. In this case the implicit label has no effect. However, if such a method misses arguments for its implicit parameters, such arguments will be automatically provided.
16+
A method can have an _implicit_ parameter list, marked by the _implicit_ keyword at the start of the parameter list. If the parameters in that parameter list are not passed as usual, Scala will look if it can get an implicit value of the correct type, and if it can, pass it automatically.
1717

18-
The actual arguments that are eligible to be passed to an implicit parameter fall into two categories:
18+
The places Scala will look for these parameters fall into two categories:
1919

20-
* First, eligible are all identifiers x that can be accessed at the point of the method call without a prefix and that denote an implicit definition or an implicit parameter.
21-
* Second, eligible are also all members of companion modules of the implicit parameter's type that are labeled implicit.
20+
* Scala will first look for implicit definitions and implicit parameters that can be accessed directly (without a prefix) at the point the method with the implicit parameter block is called.
21+
* Then it looks for members marked implicit in all the companion objects associated with the implicit candidate type.
2222

23-
In the following example we define a method `sum` which computes the sum of a list of elements using the monoid's `add` and `unit` operations. Please note that implicit values can not be top-level, they have to be members of a template.
23+
A more detailed guide to where scala looks for implicits can be found in [the FAQ](//docs.scala-lang.org/tutorials/FAQ/finding-implicits.html)
24+
25+
In the following example we define a method `sum` which computes the sum of a list of elements using the monoid's `add` and `unit` operations. Please note that implicit values can not be top-level.
2426

2527
```tut
26-
abstract class SemiGroup[A] {
28+
abstract class Monoid[A] {
2729
def add(x: A, y: A): A
28-
}
29-
abstract class Monoid[A] extends SemiGroup[A] {
3030
def unit: A
3131
}
32-
object ImplicitTest extends App {
33-
implicit object StringMonoid extends Monoid[String] {
32+
33+
object ImplicitTest {
34+
implicit val stringMonoid: Monoid[String] = new Monoid[String] {
3435
def add(x: String, y: String): String = x concat y
3536
def unit: String = ""
3637
}
37-
implicit object IntMonoid extends Monoid[Int] {
38+
39+
implicit val intMonoid: Monoid[Int] = new Monoid[Int] {
3840
def add(x: Int, y: Int): Int = x + y
3941
def unit: Int = 0
4042
}
43+
4144
def sum[A](xs: List[A])(implicit m: Monoid[A]): A =
4245
if (xs.isEmpty) m.unit
4346
else m.add(xs.head, sum(xs.tail))
44-
45-
println(sum(List(1, 2, 3))) // uses IntMonoid implicitly
46-
println(sum(List("a", "b", "c"))) // uses StringMonoid implicitly
47+
48+
def main(args: Array[String]): Unit = {
49+
println(sum(List(1, 2, 3))) // uses IntMonoid implicitly
50+
println(sum(List("a", "b", "c"))) // uses StringMonoid implicitly
51+
}
4752
}
4853
```
4954

50-
This example uses a structure from abstract algebra to show how implicit parameters work. A semigroup, modeled by `SemiGroup` here, is an algebraic structure on a set of `A` with an (associative) operation, called `add` here, that combines a pair of `A`s and returns another `A`.
55+
`Monoid` defines an operation called `add` here, that combines a pair of `A`s and returns another `A`, together with an operation called `unit` that is able to create some (specific) `A`.
56+
57+
To show how implicit parameters work, we first define monoids `StringMonoid` and `IntMonoid` for strings and integers, respectively. The `implicit` keyword indicates that the corresponding object can be used implicitly.
5158

52-
A monoid, modeled by `Monoid` here, is a semigroup with a distinguished element of `A`, called `unit`, that when combined with any other element of `A` returns that other element again.
59+
The method `sum` takes a `List[A]` and returns an `A`, which takes the initial `A` from `unit`, and combines each next `A` in the list to that with the `add` method. Making the parameter `m` implicit here means we only have to provide the `xs` parameter when we call the method if Scala can find a an implict `Monoid[A]` to use for the implicit `m` parameter.
5360

54-
To show how implicit parameters work, we first define monoids `StringMonoid` and `IntMonoid` for strings and integers, respectively. The `implicit` keyword indicates that the corresponding object can be used implicitly, within this scope, as a parameter of a function marked implicit.
61+
In our `main` method we call `sum` twice, and only provide the `xs` parameter. Scala will now look for an implicit in the scope mentioned above. The first call to `sum` passes a `List[Int]` for `xs`, which means that `A` is `Int`. The implicit parameter list with `m` is left out, so Scala will look for an implicit of type `Monoid[Int]`. The first lookup rule reads
5562

56-
Method `sum` takes a `List[A]` and returns an `A`, which represents the result of applying the monoid operation successively across the whole list. Making the parameter `m` implicit here means we only have to provide the `xs` parameter at the call site, since if we have a `List[A]` we know what type `A` actually is and therefore what type `Monoid[A]` is needed. We can then implicitly find whichever `val` or `object` in the current scope also has that type and use that without needing to specify it explicitly.
63+
> Scala will first look for implicit definitions and implicit parameters that can be accessed directly (without a prefix) at the point the method with the implicit parameter block is called.
5764
58-
Finally, we call `sum` twice, with only one parameter each time. Since the second parameter of `sum`, `m`, is implicit, its value is looked up in the current scope, based on the type of monoid required in each case, meaning both expressions can be fully evaluated.
65+
`intMonoid` is an implicit definition that can be accessed directly directly in `main`. It is also of the correct type, so it's passed to the sum method automatically.
5966

60-
Here is the output of the Scala program:
67+
The second call to `sum` passes a `List[String]`, which means that `A` is `String`. Implicit lookup will go the same way as with `Int`, but will this time find `stringMonoid`, and passes that automatically as `m`.
6168

69+
The program will output
6270
```
6371
6
6472
abc

0 commit comments

Comments
 (0)
0