Skip to content

Commit 9acaa81

Browse files
soronpojvican
soronpo
authored andcommitted
Split SIP33 into two SIPs (#905)
* Splitting SIP33 * New SIP files * Updates SIP 33 and new SIP-NN(prefix types) * Added updated PR links * redundant file * Update to prefix types SIP, according to feedback on the PR. * Update to SIP33 and added example to prefix types use * Minor grammer change. * Update history table
1 parent 0cf9f94 commit 9acaa81

File tree

3 files changed

+345
-239
lines changed

3 files changed

+345
-239
lines changed

_sips/sips/2017-02-07-make-types-behave-like-expressions.md

Lines changed: 0 additions & 239 deletions
This file was deleted.
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
---
2+
layout: sip
3+
discourse: true
4+
title: SIP-33 - Priority-based infix type precedence
5+
6+
vote-status: pending
7+
permalink: /sips/:title.html
8+
---
9+
10+
**By: Oron Port**
11+
12+
## History
13+
14+
| Date | Version |
15+
| ------------- | ---------------------------------------- |
16+
| Feb 7th 2017 | Initial Draft |
17+
| Feb 9th 2017 | Updates from feedback |
18+
| Feb 10th 2017 | Updates from feedback |
19+
| Aug 8th 2017 | Numbered SIP, improve view, fixed example, and added related issues |
20+
| Oct 20th 2017 | Added implementation link |
21+
| Oct 25th 2017 | Moved prefix types to [another SIP](http://docs.scala-lang.org/sips/adding-prefix-types.html), changed title and PR |
22+
| Nov 29th 2017 | Updated SIP according to feedback in the PR |
23+
24+
25+
Your feedback is welcome! If you're interested in discussing this proposal, head over to [this](https://contributors.scala-lang.org/t/sip-nn-make-infix-type-alias-precedence-like-expression-operator-precedence/471) Scala Contributors thread and let me know what you think.
26+
27+
---
28+
29+
## Introduction
30+
Currently scala allows symbol operators (`-`, `*`, `~~>`, etc.) for both type names and definition names.
31+
Unfortunately, there is a 'surprise' element since the two differ in behavior. While infix types are 'mostly' left-associative, the expression operation precedence is determined by the operator's first character (e.g., `/` is precedent to `+`). Please see [Infix Types](http://scala-lang.org/files/archive/spec/2.12/03-types.html#infix-types) and [Infix Operations](http://scala-lang.org/files/archive/spec/2.12/06-expressions.html#infix-operations) sections of the Scala specifications for more details.
32+
33+
**Infix expression precedence vs. infix type precedence example**:
34+
35+
```scala
36+
object InfixExpressionPrecedence {
37+
case class Nummy(expand : String) {
38+
def + (that : Nummy) : Nummy = Nummy(s"Plus[$this,$that]")
39+
def / (that : Nummy) : Nummy = Nummy(s"Div[$this,$that]")
40+
}
41+
object N1 extends Nummy("N1")
42+
object N2 extends Nummy("N2")
43+
object N3 extends Nummy("N3")
44+
object N4 extends Nummy("N4")
45+
//Both expand to Plus[Plus[N1,Div[N2,N3]],N4]
46+
assert((N1 + N2 / N3 + N4).expand == (N1 + (N2 / N3) + N4).expand)
47+
}
48+
object InfixTypePrecedence {
49+
trait Plus[N1, N2]
50+
trait Div[N1, N2]
51+
type +[N1, N2] = Plus[N1, N2]
52+
type /[N1, N2] = Div[N1, N2]
53+
trait N1
54+
trait N2
55+
trait N3
56+
trait N4
57+
//Error!
58+
//Left expands to Plus[Div[Plus[N1,N2],N3],N4] (Surprising)
59+
//Right expands to Plus[Plus[N1,Div[N2,N3]],N4]
60+
implicitly[(N1 + N2 / N3 + N4) =:= (N1 + (N2 / N3) + N4)]
61+
}
62+
```
63+
64+
---
65+
66+
## Motivation
67+
It is easier to reason about the language when mathematical and logical operations for both terms and types are expressed the same.
68+
69+
### Motivating examples
70+
71+
#### Dotty infix type similarity
72+
Dotty infix type associativity and precedence seem to act the same as expressions.
73+
No documentation available to prove this, but the infix example above works perfectly in dotty.
74+
75+
Dotty has no prefix types, same as Scalac.
76+
77+
#### Singleton-ops library example
78+
The [singleton-ops library](https://github.com/fthomas/singleton-ops) with [Typelevel Scala](https://github.com/typelevel/scala) (which implemented [SIP-23](http://docs.scala-lang.org/sips/pending/42.type.html)) enable developers to express literal type operations more intuitively. For example:
79+
80+
```scala
81+
import singleton.ops._
82+
83+
val four1 : 4 = implicitly[2 + 2]
84+
val four2 : 2 + 2 = 4
85+
val four3 : 1 + 3 = implicitly[2 + 2]
86+
87+
class MyVec[L] {
88+
def doubleSize = new MyVec[2 * L]
89+
def nSize[N] = new MyVec[N * L]
90+
}
91+
object MyVec {
92+
implicit def apply[L](implicit check : Require[L > 0]) : MyVec[L] = new MyVec[L]()
93+
}
94+
val myVec : MyVec[10] = MyVec[4 + 1].doubleSize
95+
val myBadVec = MyVec[-1] //fails compilation, as required
96+
```
97+
98+
We currently loose some of the intuitive appeal due to the precedence issue:
99+
100+
```scala
101+
val works : 1 + (2 * 3) + 4 = 11
102+
val fails : 1 + 2 * 3 + 4 = 11 //left associative:(((1+2)*3)+4))) = 13
103+
```
104+
105+
#### Developer issues example
106+
[This](http://stackoverflow.com/questions/23333882/scala-infix-type-aliasing-for-2-type-parameters) stackoverflow question demonstrate developers are 'surprised' by the difference in infix precedence, expecting infix type precedence to act the same as expression operations.
107+
108+
---
109+
110+
## Proposal
111+
112+
Make infix types conform to the same precedence and associativity traits as term operations.
113+
114+
------
115+
116+
## Implementation
117+
118+
A PR for this SIP is available at: [https://github.com/scala/scala/pull/6147](https://github.com/scala/scala/pull/6147)
119+
120+
------
121+
122+
### Interactions with other language features
123+
124+
#### Star `*` infix type interaction with repeated parameters
125+
The [repeated argument symbol `*`](https://www.scala-lang.org/files/archive/spec/2.12/04-basic-declarations-and-definitions.html#repeated-parameters) may create confusion with the infix type `*`.
126+
Please note that this feature interaction already exists within the current specification.
127+
128+
```scala
129+
trait +[N1, N2]
130+
trait *[N1, N2]
131+
trait N1
132+
trait N2
133+
def foo(a : N1*N1+N2*) : Unit = {} //repeated parameter of type +[*[N1, N1], N2]
134+
```
135+
136+
However, it is very unlikely that such interaction would occur.
137+
138+
**Related Issues**
139+
140+
* [Dotty Issue #1961](https://github.com/lampepfl/dotty/issues/1961)
141+
142+
143+
## Backward Compatibility
144+
Changing infix type associativity and precedence affects code that uses type operations and conforms to the current specification.
145+
146+
Note: changing the infix precedence didn't fail any scalac test.
147+
148+
---
149+
150+
### Bibliography
151+
[Scala Contributors](https://contributors.scala-lang.org/t/sip-nn-make-infix-type-alias-precedence-like-expression-operator-precedence/471)
152+
153+
[scala-sips](https://groups.google.com/forum/#!topic/scala-sips/ARVf1RLDw9U)

0 commit comments

Comments
 (0)