After playing with these three alternatives for a while, here’s my evaluation:
There are three different “levels” of implicit definitions: instance definitions, context parameters, and context functions (i.e. implicit function types and closures). I believe it is best if each level has a different syntax. It’s less regular, but a lot easier to parse. That sentiment was also brought up in several comments on this thread.
There are several classes of implicit uses. The most important ones are
- Context passing
- Typeclasses
- Proofs
- Conversions
- Extensions
Extensions have their own syntax now, and proofs and conversions can be seen as special cases of typeclasses. So that leaves “context passing” and “typeclasses” as the two principal flavors of implicits.
Let’s name the three explored alternatives after the name of the instance. followed by the name indicating contextual parameters. So it’s witness/given
, default/given
, and given/with
. Here’s my evaluation how suitable these three combinations are for the two principal use classes:
context passing typeclasses
witness/given - +
default/given ++ -
given/with + +
given/with
has the edge in that it works for both use classes equally well, so I am pursuing this alternative further. PR 8017 is a complete implementation. In this implementation, both the previous given/given
syntax and the new given/with
syntax are supported, but the alternative to use =>
for conditional givens introduced in 0.20 has been removed. My plan is to get this merged by the next Dotty release early February, and to switch everything to the new syntax afterwards. In the PR the tests already use the new syntax but the main implementation does not.
We would then use one or two 6 weeks release cycles to try the new syntax in depth, and hopefully come to a final decision afterwards. I had hoped that we would be in feature freeze by now, but it’s very important to get this right, so I think we should give ourselves the time needed to reflect on this.