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.