Skip to content

Commit ebe6ba6

Browse files
committed
Initial draft for multiple implicit parameter lists SIP
1 parent 47a1df0 commit ebe6ba6

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
layout: sip
3+
disqus: true
4+
title: SIP-NN - SIP Allow multiple implicit parameter lists
5+
---
6+
7+
**By: Miles Sabin and Merlin Göttlinger**
8+
9+
## History
10+
11+
| Date | Version |
12+
|---------------|---------------|
13+
| Apr 21st 2016 | Initial Draft |
14+
15+
## Motivation
16+
17+
In Scala the implicit parameters of a function are limited to being placed in the single very last parameter list of a function. This prevents later parameters from using dependant types of former ones as this is only allowed between, but not inside a single parameter list. Another issue introduced by this restriction is, that if you want to explicitly specify one of the implicit parameters you have to specify all of them by hand (or write `implicitly` in place of every other parameter that should be filled by the compiler).
18+
19+
## Motivating Examples
20+
21+
### Examples
22+
23+
For regular parameter lists it is possible to write the following:
24+
{% highlight scala %}
25+
trait A { type B }
26+
27+
def works(a: A)(b: a.B) = "works"
28+
{% endhighlight %}
29+
Due to the restriction of being contained in a single parameter list the implicits can't benefit from this goodness. A common workaround is to pull the type member `B` into a type parameter of a new `Aux` object and having this as a type parameter of your function:
30+
{% highlight scala %}
31+
trait A { type B }
32+
object A { type Aux[D] = A { type B = D } }
33+
34+
def works[B](implicit a: A.Aux[B], b: B) = "works"
35+
{% endhighlight %}
36+
While this works it introduces unnecessary complexity because our method shouldn't need to have type parameters and we shouldn't need the `Aux` object just to use the type member of `A` for implicits.
37+
38+
With the proposed change of allowing multiple implicit parameter lists the example would again be reduced to the following concise and readable example:
39+
{% highlight scala %}
40+
trait A { type B }
41+
42+
def worksWithImplicits(implicit a: A)(b: a.B) = "pls make me work"
43+
{% endhighlight %}
44+
45+
Another benefit mentioned before would be that implicit parameters, that are expected to often be filled in manually can be put in separate lists.
46+
{% highlight scala %}
47+
def now(implicit a: Int, b: String) = b * a
48+
now(1, implicitly)
49+
50+
def then(implicit a: Int)(b: String) = b * a
51+
then(1)
52+
{% endhighlight %}
53+
54+
## Implementation
55+
56+
The implementation of this change is as simple as removing the artificial restriction of having only one parameter list in the `Parser`. A pull request (#5108) from Miles Sabin already implements this change as well as an accompanying test file. The change should not affect any existing code as every Scala statement that was valid before will still be valid after the change. There will even be binary compatibility in both directions.
57+
58+
## Drawbacks
59+
60+
The current simple implementation may not make it obvious from first glance that parameter lists coming after a implicit list are also implicit.
61+
62+
## References
63+
64+
1. [Miles' PR][1]
65+
66+
[1]: https://github.com/scala/scala/pull/5108 "PR#5108"

0 commit comments

Comments
 (0)