Skip to content
This repository has been archived by the owner on Sep 1, 2020. It is now read-only.

Allow multiple implicit parameter blocks #8

Closed
puffnfresh opened this issue Sep 4, 2014 · 10 comments
Closed

Allow multiple implicit parameter blocks #8

puffnfresh opened this issue Sep 4, 2014 · 10 comments
Assignees
Milestone

Comments

@puffnfresh
Copy link

Method signatures can currently only have a single implicit parameter block, which means that explicitly specifying an implicit parameter requires every parameter to be specified, and limits opportunities for the type of one implicit parameter to drive the type inference of another.

Miles:

Arbitrary interleaving of implicit and explicit parameter blocks, a la Agda seems like a good way to go. I don't think there will be any major issues from a typing point of view. The trickiest issue is how this works out a call sites ... Paolo Giarrusso had a nice language extension proposal at some point, introducing a new bracket style for explicitly provided implicit argument lists (again a la Agda) which is probably worth investigating. I'll see if I can dig it out and/or mail him about it.

@Blaisorblade
Copy link

I was drafting an email about this, with an intro and everything. I made some light editing, but here's the first part. This should not be news to Miles at least.

Last year I gave a short talk at the Scala workshop on this, and last year I wrote a blog post about the idea.

The goal is to support better use cases such as:

def foo(a: Universe)(b: a.Tree): C => D

Each foo caller needs to specify both a and b, even though passing b would be enough to deduce a. To avoid this problem, I proposed allowing implicit parameter lists at arbitrary positions:

def foo[[a: Universe]](b: a.Tree): C => D

This method could be invoked as foo(b), passing only b. In Typesafe Scala, this call syntax would be misunderstood as passing only a, because foo(a) and foo(a)(b) are supported. However, to pass a explicitly here you would have to write foo[a]: this way, it is easy to see whether a parameter list is implicit or explicit at the call site.

For more details, I refer you to the above blog post.

However, this is not yet detailed enough for a specification. Comments are welcome!

In particular, adding this to a compiler fork creates additional compatibility problems.

This extends which method signatures are valid with more syntactic sugar, so we need to figure out how Typesafe Scala and Typelevel Scala interoperate. We were last discussing that:

(a) For Typelevel Scala, instead, we'd need to store extra information in the Scala-visible method signature. Either as additional info or as a separate attribute.

(b) For Typesafe Scala, Miles proposed that an implicit parameter list not at the end of a method call should "erase" to a normal parameter list. So a library using the new feature would get essentially the same signatures as today (apart from the split into parameter lists).

@Blaisorblade
Copy link

After the IRC discussion with @milessabin, I realized a potential issue with this proposal.

With the current proposal, the syntax calling a method with such an extended signature depends on the Scala dialect you're using. There's no way to call such a method which is valid in both dialects.

However, this only happens if you take advantage of the new syntax for defining the method!

Example:

//Typelevel-Scala definition:
def foo[[a: Universe]](b: a.Tree): C => D
//As seen by Typesafe-Scala:
def foo(a: Universe)(b: a.Tree): C => D


//At the call-site:
val a: Universe = ...
val b: a.Tree = ...
val c: C = ...

//Typelevel-Scala possible call sites
foo(b) //expands to:
foo[[a]](b)
//And has type : C => D
//But:
// foo(a)(b) //Rejected!
// foo(a)(b)(c) //Rejected!
// because that syntax is reserved for:
foo(b)(c) //Accepted :-)


//Typesafe-Scala possible call-sites:
foo(a)(b)
foo(a)(b)(c)

The only workarounds I see are:

  • allow foo(a)(b) with some annotation which is ignored by Typesafe Scala and accepted by Typelevel Scala. I don't like this.
  • one could give the erased signature to a foo_legacy method (better schemes are welcome), which could be called in both dialects with the Typesafe-Scala syntax:
//Common subset:

foo_legacy(a)(b)
foo_legacy(a)(b)(c)

Neither solution is really pretty, and I suspect trying to achieve source compatibility, or having these methods callable from Typesafe Scala, means looking for trouble.

@Blaisorblade
Copy link

For the record, @milessabin answered on IRC: "We aren't maintaining source compatability, only binary."

@Blaisorblade
Copy link

See also #14 on compatibility.

aloiscochard pushed a commit to aloiscochard/scala that referenced this issue Sep 5, 2014
@Blaisorblade
Copy link

For Typelevel Scala [...] we'd need to store extra information in the Scala-visible method signature. Either as additional info or as a separate attribute.

From @propensive's suggestion on #44, I realized we could encode implicitness using an annotation on the 1st parameter of the implicit parameter list. For internal consistency, we might want to add @implicit to (EDIT) standard parameter lists. Or maybe it doesn't help and we need to paper over the difference internally.

This annotation should probably have the same caveats as code in scala.runtime: that is, only to be used by the compiler.

@milessabin
Copy link
Member

Nice idea @propensive :-)

puffnfresh pushed a commit to puffnfresh/scala that referenced this issue Jul 30, 2015
Spec update for signature polymorphic methods
@fommil
Copy link

fommil commented Nov 7, 2015

has anyone ever reported this with scala-lang and been assigned an SI- ticket for it?

@Blaisorblade
Copy link

has anyone ever reported this with scala-lang and been assigned an SI- ticket for it?

Not to my knowledge; I talked about this with Martin Odersky and he was skeptical.

@milessabin
Copy link
Member

To resurrect this issue, please rework it as an issue/PR against Lightbend Scala (ie. scala/scala).

@milessabin milessabin added this to the Parked milestone Aug 12, 2016
@SethTisue
Copy link
Member

there is a SIP at scala/docs.scala-lang#520

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants