I’d like to propose a variant that I think maximizes readability + regularity. It’s mostly a combination of what’s been discussed before, with one novel idea.The gist of it is this:
given [T] if Ord[T] for Ord[List[T]] { ... }
given if (outer: Context) for Context = ...
def foo(given Context) = { ... }
More examples can be found here.
There are four notable points:
(1) Keyword for
precedes the type (instead of “as” or “of”).
(2) Keyword if
is used for conditional instances (instead of “with” or “given”).
(3) Same keyword given
for instances and parameters.
(4) Parentheses around given parameters.
I’ll comment a bit on each point.
(1) The for
variant translates better into real-world language. How to read it:
Example: given for Ord[Int] { }
Two alternatives that are mostly synonymous:
a) Using “given” as adjective, i.e. “a given instance”: Let there be defined a given instance for Ord of Int with the following implementation.
b) Using “given” as verb, i.e “x is given for y”: Let there be given for Ord of Int an instance with the following implementation.
(2) I think the idea has been that conditional instances and context parameter should have the same syntax. This is a legacy from the original implicit
syntax. The new, high-level abstraction is conditional given instances. There is no notion of “parameters” here, and as such it can have a completely unique syntax. with
does not have any connotations of “conditionality”, thus if
.
How to read it:
Example: given [T] if Ord[T] for Ord[List[T]] { }
a) Let there be defined, for any type T, if there exists a given instance for Ord of T, a given instance for Ord of List of T with the following implementation.
b) Let there, for any type T, if there exists a given instance for Ord of T, be given for List of Ord of T an instance with the following implementation.
(roughly)
(3) I think there should be some kind of symmetry between context instances and context parameters. Using the same keyword is a simple way to achieve that. The alternative with
has the following problems:
- it’s a bit overloaded
- it does not have any connotation of “implicitness”
- it does not have any semantic relationship with “given”
- used without parentheses, it has a syntax collision with
new Foo with Bar
- it requires additional syntax for context function types
(4) Using parentheses around context parameters avoids the “warts” of .given
and spaces around :
.