Proposal to Add Implied Instances to the Language

Yeah, like renaming “null” to “uninitialized”, because people hate null.

3 Likes

At least from what I’ve seen, there are 2 aims of this proposal:

  1. Remove the capability for implicit conversions
  2. Tweak the syntax to encourage the best-practice usages of implicits

While I think that the proposal veers a bit further toward “punish certain usage of implicits” than I’m strictly comfortable with, overall I agree with the general direction. While there is an element of rebranding, I think it’s generally a means to an end (breaking old behavior patterns), more than an end goal.

Restricting implicit conversions was dealt with before this proposal. This proposal is just about changing the syntax of implicits.

As I’ve said before… it’s really not necessary to push this through for 3.0. There really is a lot that isn’t certain, and a lot of risk. It would be much safer not to merge this until there’s a greater amount of consensus.

One point that has been made several times is that this new syntax is much more appealing to newcomers than to Scala experts. That’s true but I’m not sure what conclusion that points to. I mean you don’t want to make a language only friendly to experts, but you also don’t want to introduce things that experts say there’s no value in.

I think there’s room for improvement but we have to get it right, and I don’t think we’re there yet. Please let’s wait until we’re more sure. Until then let’s fix whatever can be fixed without breaking code, and isn’t controversial. We’ll be in a much better position to know then.

5 Likes

Regarding the concrete proposal of implied instance definitions discussed in this thread: After more deliberations I drop my suggestion to use implicit as a noun. I believe @jdegoes observation that it would lead to more confusion for current users as well as outsiders holds, and trumps any advantages of familiarity.

We have discussed many alternatives to the original implied for syntax, but none of the alternatives has garnered enough support to be clearly preferable. I’ll stick therefore to the original proposal, with two modifications:

  • given comes last.
  • the right-hand side of an implied alias instance without type parameters or given clause is cached.
9 Likes

I’m glad to hear this and think the (noted) lack of initial familiarity will be more than compensated by the reduced confusion and clearer migration path going forward.

It also looks like two very useful (if small) modifications came out of this discussion, which means everyone who contributed to this thread made positive contributions to the development of this language feature. Thanks to all for the great feedback!

1 Like

See: Principles for Implicits in Scala 3

Here’s another update: After consulting with the SIP commitee and some other people I changed the syntax of instance definitions at the last possible moment before ScalaDays from implied to delegate. The new Dotty Docs reflect the change. Consensus seems to be that the change was indeed an improvement, even though not everyone is unequivocally happy with this syntax either.

As previously announced, we will try out the feature for a while before deciding to settle for it.

4 Likes

I beg the Scala community to reconsider the “delegate” keyword. Having mentored developers in Scala I know how hard it is to grasp the concepts around implicits. I’m confident that the larger set of changes to syntax and semantics around extension methods, “delegates” and type classes will help Scala learners tremendously. Thank you Odersky and the Scala community for these fantastic changes! However, I think the choice of word “delegate” is a big mistake that would become a road block to learners of the language. As a verb it conveys that someone is passing work along to someone else. As a noun it means a representitive. Neither of these meanings helps with comprehension in its proposed usage in Scala. Even worse, the word has been used to describe an object oriented design pattern, again having no connection with implicits. I think “implied” was better, though I agree a noun would be preferrable. So I’d like to suggest the keyword become “default”. This would make it far easier to explain - that this is the instance of that type that will be used - by default - as long as it is in scope. You might also consider “supplied” or “provided”. These convey that this is the instance of the required type that will be provided when you declare that you need one with the “given” keyword.
In Odersky’s recent talk, one slide said “In the end, it will not matter, just need a noun that’s easy to remember.” I disagree. The choice of keyword will have a real impact on the ease of learning Scala. Please take this seriously and take time to consider alternatives. A good choice of keywords will help make the concepts more self-explanatory. A poor choice will confuse and alienate potential Scala developers. Thank you!

1 Like

Must admit, I quite like provide/provided here - it works quite well with the plain english constructs such as “provided that X then Y” or “You can go to the party provided that you’ve done your homework”

Another possibility that it suggests is “introduce”

I believe that “introduce” is a bit too general. We actually already have a bunch of more-particular name-introduction keywords, each with a different particular purpose: val, var, def, class, trait, and type. Therefore, I think and new name-introduction keyword needs to be similarly-particular.

I think that “provider” would be more consistent than “provide”, given than the rest of the name-introduction keywords are all nouns.

Given that we seem to still be playing “introduction keyword bikeshed”, how do proof or proven sound to folks?

How about standard?

It seems to work well out loud, as in “the standard instance for integer ordering,” as well as in code:

// Long form:
standard IntMonoid for Monoid[Int] { ... }
// Short form:
standard for Monoid[Int] { ... }

// Extension method:
standard {
  def (xs: List[T]) second[T] = xs.tail.head
}
1 Like

How about fallback?

See: https://github.com/lampepfl/dotty/pull/6773

1 Like

Or, for the people too lazy to follow up a link, “given X as Y”. Eg, “given IntMonoid as Monoid[Int]”. Still all experimental.

Looking at synonyms for “delegate (n)”, I like “stand-in” (standin) from a coding perspective, and “plenipotentiary” without that perspective. :slight_smile:

Let the records show I still really like verbing it, despite that being outside the boudary conditions and also while brainstorming is really over.

take ListOrd[A] as Ord[List[A]] given Ord[A]

One weird thing I noticed when trying out Dotty in the REPL is the following:
I defined a trait:

scala> trait Semigroup[A] {
     |   def (a: A) combine (b: A): A
     | }

and then try to define an instance on String:

scala> given Semigroup[String] {
     |   def (a: String) combine (b: String): String = a + b
     | }

But get the super confusing error:

2 |  def (a: String) combine (b: String): String = a + b
  |                                                    ^
  |  Found:    String(b)
  |  Required: String'
  |
  |  where:    String  is a type in class Semigroup
  |            String' is a type in object Predef which is an alias of String

Well turns out I was missing the as keyword and I was suppose to actually type:

given as Semigroup[String] { .. }

Which is weird. I don’t know why the first one compiles. I assume it was translate into something akin to

class Semigroup[String] {
  def (a: String) combine (b: String): String = a + b
}

As in, the String there is a name of a type parameter, rather than java.String

3 Likes

You might raise this in the issue tracker, it seems like this would be fairly low-hanging fruit to detect and provide a more helpful error message

I suggested given foo: Bar/given: Bar instead of given foo as Bar/given as Bar in the Gitter channel, and was told to suggest it here.

Edit: I agree with what @smarter says here.

2 Likes

On-going discussion on the syntax of implied/given instances at: https://github.com/lampepfl/dotty/issues/7151