Skip to content

Commit 2599e2e

Browse files
committed
Address review
1 parent 2e72550 commit 2599e2e

File tree

2 files changed

+75
-62
lines changed

2 files changed

+75
-62
lines changed

docs/docs/reference/intersection-types-spec.md

Lines changed: 34 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5,70 +5,14 @@ title: "Intersection Types - More Details"
55

66
## Syntax
77

8-
Syntactically, an intersection type `S & T` is similar to an infix type,
9-
where the infix operator is `&`.
8+
Syntactically, an intersection type `S & T` is similar to an infix type, where
9+
the infix operator is `&`. `&` is treated as a soft keyword. That is, it is a
10+
normal identifier with the usual precedence. But a type of the form A & B is
11+
always recognized as an intersection type, without trying to resolve &.
1012

1113
```
1214
Type ::= ...| InfixType
1315
InfixType ::= RefinedType {id [nl] RefinedType}
14-
RefinedType ::= WithType {[nl] Refinement}
15-
WithType ::= AnnotType {‘with’ AnnotType}
16-
```
17-
18-
## Type Checking
19-
20-
The type `S & T` represents values that are of the type `S` and `T` at the same time.
21-
22-
```scala
23-
trait Resettable {
24-
def reset(): this.type
25-
}
26-
trait Growable[T] {
27-
def add(x: T): this.type
28-
}
29-
def f(x: Resettable & Growable[String]) = {
30-
x.reset()
31-
x.add("first")
32-
}
33-
```
34-
35-
The value `x` is required to be _both_ a `Resettable` and a
36-
`Growable[String]`.
37-
38-
The members of an intersection type `A & B` are all the members of `A` and all
39-
the members of `B`. For instance `Resettable & Growable[String]`
40-
has member methods `reset` and `add`.
41-
42-
If a member appears in both `A` and `B`, its type in `A & B` is the intersection
43-
of its type in `A` and its type in `B`. For instance, assume the definitions:
44-
45-
```scala
46-
trait A {
47-
def children: List[A]
48-
}
49-
trait B {
50-
def children: List[B]
51-
}
52-
val x: A & B = new C
53-
val ys: List[A & B] = x.children
54-
```
55-
56-
The type of `children` in `A & B` is the intersection of `children`'s
57-
type in `A` and its type in `B`, which is `List[A] & List[B]`. This
58-
can be further simplified to `List[A & B]` because `List` is
59-
covariant.
60-
61-
An intersection type `A & B` may not be inhabited, e.g. `Int & String` is not inhabited.
62-
`A & B` is just a type that represents a set of requirements for
63-
values of the type. At the point where a value is _constructed_, one
64-
must make sure that all inherited members are correctly defined.
65-
So if one defines a class `C` that inherits `A` and `B`, one needs
66-
to give at that point a definition of a `children` method with the required type.
67-
68-
```scala
69-
class C extends A with B {
70-
def children: List[A & B] = ???
71-
}
7216
```
7317

7418
## Subtyping Rules
@@ -91,6 +35,36 @@ From the rules above, we can show that `&` is _commutative_: `A & B <: B & A` fo
9135
In another word, `A & B` is the same type as `B & A`, in that sense that the two types
9236
have the same values and are subtypes of each other.
9337

38+
If `C` is a type constructor, the join `C[A] & C[B]` is simplified by pulling the
39+
intersection inside the constructor, using the following two rules:
40+
41+
- If `C` is covariant, `C[A] & C[B] ~> C[A & B]`
42+
- If `C` is contravariant, `C[A] & C[B] ~> C[A | B]`
43+
44+
When `C` is covariant, `C[A & B] <: C[A] & C[B]` can be derived:
45+
46+
```
47+
A <: A B <: B
48+
---------- ---------
49+
A & B <: A A & B < B
50+
--------------- -----------------
51+
C[A & B] <: C[A] C[A & B] <: C[B]
52+
------------------------------------------
53+
C[A & B] <: C[A] & C[B]
54+
```
55+
56+
When `C` is contravariant, `C[A | B] <: C[A] & C[B]` can be derived:
57+
58+
```
59+
A <: A B <: B
60+
---------- ---------
61+
A <: A | B B < A | B
62+
------------------- ----------------
63+
C[A | B] <: C[A] C[A | B] <: C[B]
64+
--------------------------------------------------
65+
C[A | B] <: C[A] & C[B]
66+
```
67+
9468
## Erasure
9569

9670
The erased type for `S & T` is the erased _glb_ (greatest lower bound) of the

docs/docs/reference/intersection-types.md

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ title: "Intersection Types"
55

66
Used on types, the `&` operator creates an intersection type.
77

8+
## Type Checking
9+
10+
The type `S & T` represents values that are of the type `S` and `T` at the same time.
11+
812
```scala
913
trait Resettable {
1014
def reset(): this.type
@@ -21,8 +25,43 @@ def f(x: Resettable & Growable[String]) = {
2125
The value `x` is required to be _both_ a `Resettable` and a
2226
`Growable[String]`.
2327

24-
The members of an intersection type `A & B` are all the members of `A`
25-
and all the members of `B`. For instance `Resettable & Growable[String]`
28+
The members of an intersection type `A & B` are all the members of `A` and all
29+
the members of `B`. For instance `Resettable & Growable[String]`
2630
has member methods `reset` and `add`.
2731

32+
If a member appears in both `A` and `B`, its type in `A & B` is the intersection
33+
of its type in `A` and its type in `B`. For instance, assume the definitions:
34+
35+
```scala
36+
trait A {
37+
def children: List[A]
38+
}
39+
trait B {
40+
def children: List[B]
41+
}
42+
val x: A & B = new C
43+
val ys: List[A & B] = x.children
44+
```
45+
46+
The type of `children` in `A & B` is the intersection of `children`'s
47+
type in `A` and its type in `B`, which is `List[A] & List[B]`. This
48+
can be further simplified to `List[A & B]` because `List` is
49+
covariant.
50+
51+
One might wonder how the compiler could come up with a definition for
52+
`children` of type `List[A & B]` since all its is given are `children`
53+
definitions of type `List[A]` and `List[B]`. The answer is it does not
54+
need to. `A & B` is just a type that represents a set of requirements for
55+
values of the type. At the point where a value is _constructed_, one
56+
must make sure that all inherited members are correctly defined.
57+
So if one defines a class `C` that inherits `A` and `B`, one needs
58+
to give at that point a definition of a `children` method with the required type.
59+
60+
```scala
61+
class C extends A with B {
62+
def children: List[A & B] = ???
63+
}
64+
```
65+
66+
2867
[More details](./type-lambdas-spec.html)

0 commit comments

Comments
 (0)