Updated Proposal: Revisiting Implicits

EDIT: this is very similar to the link @julienrf posted just above, I didn’t see it until after I posted this message!

I agree that the syntax for given instances looks like a hybrid thing, by contract given aliases seem more natural to me. So could we drop given instances? This would be one less thing to teach! Instead of:

trait Foo { def foo: Int }
given Foo {
  def foo: Int = 1
}

we can use a given alias:

given Foo = new Foo {
  def foo: Int = 1
}

The former translates to an object, the latter translate to a lazy val and an anonymous class, those should be semantically equivalent.

And instead of:

trait Bar[T](x: T) { def foo: T }
given (given x: Int): Bar[Int](x) {
  def bar: Int = 1
}

we can also use a given alias:

given (given x: Int): Bar[Int] = new Bar[Int](x) {
  def bar: Int = 1
}

The former translates to a class and a def, the latter also translates to a class and a def and the semantics are again equivalent as far as I can tell.

Of course, the main issue here is the repetition, so let’s invent even more syntax (sorry!):

given Foo = new {
  def foo: Int = 1
}
given (given x: Int): Bar[Int] = new(x) {
  def bar: Int = 1
}

The unparameterized version actually already works in Dotty, the parameterized one has been suggested before by @propensive in a more general context, and @odersky gave some reasons it might not be worth it in Expunging `new` from scala 3 - #124 by odersky, but I think it’s worth revisiting in the context of givens: it it allows us to drop given instances that would be a huge simplification and more than make up the extra complexity it introduces.

2 Likes