Skip to content

Commit fcaa284

Browse files
committed
Add section in intersection types
1 parent 6cf0f48 commit fcaa284

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
layout: doc-page
3+
title: "Intersection Types"
4+
---
5+
6+
Used on types, the `&` operator creates an intersection type.
7+
8+
```scala
9+
trait Resetable {
10+
def reset(): this.type
11+
}
12+
trait Growable[T] {
13+
def add(x: T): this.type
14+
}
15+
def f(x: Resetable & Growable[String]) = {
16+
x.reset()
17+
x.add("first")
18+
}
19+
```
20+
21+
The value `x` is required to be _both_ a `Resetable` and a
22+
`Growable[String]`. Intersection types `A & B` replace compound types
23+
`A with B` in Scala 2 (for the moment, `A with B` is still allowed, but
24+
it will be deprecated and removed in the future).
25+
26+
Unlike `with` types, `&` is _commutative_: `A & B` is the same type as
27+
`B & A`.
28+
29+
The members of an intersection type `A & B` are all the members of `A`
30+
and all the members of `B`. For instance `Resetable & Growable[String]`
31+
has member methods `reset` and `add`.
32+
33+
If a member appears in both `A` and `B`, its type in `A & B` is the
34+
intersection of its type in `A` and its type in `B`. For instance, assume the definitions:
35+
36+
```scala
37+
trait A {
38+
def children: List[A]
39+
}
40+
trait B {
41+
def children: List[B]
42+
}
43+
val x: A & B = new C
44+
val ys: List[A & B] = x.children
45+
```
46+
47+
The type of `children` in `A & B` is the intersection of `children`'s
48+
type in `A` and its type in `B`, which is `List[A] & List[B]`. This
49+
can be further simplified to `List[A & B]` because `List` is
50+
covariant.
51+
52+
One might wonder how the compiler could come up with a definition for
53+
`children` of type `List[A & B]` since all its is given are `children`
54+
definitions of type `List[A]` and `List[B]`. The answer is it does not
55+
need to. `A & B` is just a type that represents a set of requirements for
56+
values of the type. At the point where a value is _constructed_, one
57+
must make sure that all inherited members are correctly defined.
58+
So if one defines a class `C` that inherits `A` and `B`, one needs
59+
to give at that point a definition of a `children` method with the required type.
60+
61+
```scala
62+
class C extends A with B {
63+
def children: List[A & B] = ???
64+
}
65+
```
66+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package intersectionTypes
2+
3+
object t1 {
4+
5+
trait Resetable {
6+
def reset(): this.type
7+
}
8+
trait Growable[T] {
9+
def add(x: T): this.type
10+
}
11+
def f(x: Resetable & Growable[String]) = {
12+
x.reset()
13+
x.add("first")
14+
}
15+
16+
}
17+
18+
object t2 {
19+
20+
trait A {
21+
def children: List[A]
22+
}
23+
trait B {
24+
def children: List[B]
25+
}
26+
val x: A & B = new C
27+
val ys: List[A & B] = x.children
28+
29+
30+
class C extends A with B {
31+
def children: List[A & B] = ???
32+
}
33+
34+
35+
}

0 commit comments

Comments
 (0)