Implicit Function Types

This looks like a great step in a very promising direction! It is a little peculiar, though, that it’s solved by muddying the distinction between arguments and return values. Of course currying already does exactly that, so it’s not like it establishes a wholly new isomorphism. But there are advantages to having arguments stay in argument position including making it easier to reason about co/contravariance (“it’s just another argument”), ease of telling what the return type actually is, and knowing where to put type parameters and such.

So I think the idea of implicit functions is great, but I wonder whether the syntax is more different than it needs to be, and the logic is more sutble than it needs to be. These two forms are equivalently compact:

def foo(i: Int): Bar[Int]
def foo(i: Int)(Bar): Int

which would require only that we say that we can list implicit types without a name in a final parameter block, and otherwise would work more or less the same as the proposal (with adjustments to precedence based on nesting).

It feels like there is an important difference, but I haven’t yet been able to clearly describe it, and since I’m necessarily not very familiar with this proposal I don’t know which is better. But my sense is certainly that the form above would be a lot more familiar.

Additionally, it doesn’t seem to fully address a second problem with implicits: sometimes you need them to do something, and it is frustrating to try to deal with them internally by calling implicitly[SomeHugeTypeName] over and over again. Implicit functions help this a little by making it easier to write methods to help you, but actually being able to name the implicit is very often important, which is why, for instance, I almost never use [A: Baz] notation instead of [A](...)(implicit baz: Baz[A]) even with all the extra boilerplate: it’s too important to have access to baz internally in the method.