Skip to content

Try to clarify implicit parameters tour #1018

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 15, 2018

Conversation

martijnhoekstra
Copy link
Contributor

  • Don't explain what a monoid and a semigroup are. This is not the place for that.
  • Don't make Monoid[A] extend Semigroup[A]. This only complicates the example for no gain.
  • Explain the lookup procedure.
  • Use "Companion object" instead of "companion module"
  • Don't mention templates. It's an uncommonly used
  • Don't extend App. It doesn't simplify the example.

Further improvements could be to show an example of the second rule of implicit lookup, and/or a chained implicit lookup.

* Don't explain what a monoid and a semigroup are. This is not the place for that.
* Don't make `Monoid[A]` extend `Semigroup[A]`. This only complicates the example for no gain.
* Explain the lookup procedure.
* Use "Companion object" instead of "companion module"
* Don't mention templates. It's an uncommonly used 
* Don't extend `App`. It doesn't simplify the example.

Further improvements could be to show an example of the second rule of implicit lookup, and/or a chained implicit lookup.

The actual arguments that are eligible to be passed to an implicit parameter fall into two categories:
The places scala will look for these parameters fall into two categories:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: capitalize "Scala" consistently

* 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.
* Second, eligible are also all members of companion modules of the implicit parameter's type that are labeled implicit.
* First, eligible are all identifiers that can be accessed at the point of the method call without a prefix and that denote an implicit definition or an implicit parameter.
* Second, eligible are also all members of companion objects of the implicit parameter's type that are labeled implicit.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it was like this, but the phrasing "eligible are all identifiers that ..." sounds like a 19th century legal text.

Why not something like...

... two categories:

  • Implicit definitions and implicit parameters that can be referenced at the point of the method call without a prefix, and
  • Members of companion objects of the implicit parameter's type that are marked implicit.

This elides the "parts" bit from the spec but I think that is needlessly complicated to mention in the tour.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The swing I took at this also addresses the two below comments. WDYT?


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.
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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consistent capitalization opportunity


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.
`IntMonoid` is an identifier, it can be accessed directly in `main`, and it is an implicit definition. It is also of the correct type, so it's passed to the sum method automatically.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe,

Because IntMonoid is a value which can be referenced directly inside of main, is marked implicit, and has the correct type, it's passed automatically to sum.

Otherwise, "sum" should probably be "sum".

def unit: A
}
object ImplicitTest extends App {

object ImplicitTest {
implicit object StringMonoid extends Monoid[String] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some gotchas with implicit objects last time I checked, and the type of StringMonoid isn't really Monoid[String]. I think this should be implicit val StringMonoid: Monoid[String] = ....

Make it read less like Ye Olde Specificatione of Ye Scaelae Language
* 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.
* Second, eligible are also all members of companion modules of the implicit parameter's type that are labeled implicit.
* 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.
* Then, it falls back to all members that are marked implicit in the companion object of the implicit parameter.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about "Then it looks for members marked implicit in all the companion objects associated with the implicit candidate type"? A link to https://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html would be useful for those that want to know more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linking to the implicit lookup FAQ there is a great idea.

The phrasing "in all the companion objects associated with the implicit candidate type" isn't as "human readable" as I'd like it to be, especially for the tour. It still reads a bit as legalese. I'll think on it some more. Maybe not saying much about where it looks exactly (but link to the FAQ for details) is another option.

Copy link
Member

@jvican jvican left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a comment regarding the implicit search explanation, but overall great work 👍

@mghildiy
Copy link
Contributor

Won't it interfere with:
#1003

As part of this work, I would remove older files related to implicits, and there would be a single implicit.md.

@SethTisue
Copy link
Member

@mghildiy yes, you'll have a bit of merging work to do in order to carry #1003 forward.

@SethTisue SethTisue merged commit 6a15f7b into scala:master Feb 15, 2018
@SethTisue
Copy link
Member

thanks Martijn & reviewers, nice work here.

@martijnhoekstra martijnhoekstra deleted the patch-3 branch December 11, 2021 09:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants