Skip to content

Commit 5dd886c

Browse files
smartersjrd
authored andcommitted
Specify type lambdas (including variance inference and subtyping)
1 parent 6261c9e commit 5dd886c

File tree

4 files changed

+75
-131
lines changed

4 files changed

+75
-131
lines changed

docs/_spec/03-types.md

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ chapter: 3
88

99
```ebnf
1010
Type ::= FunctionArgTypes ‘=>’ Type
11+
| TypeLambdaParams ‘=>>’ Type
1112
| InfixType
1213
FunctionArgTypes ::= InfixType
1314
| ‘(’ [ ParamType {‘,’ ParamType } ] ‘)’
15+
TypeLambdaParams ::= ‘[’ TypeLambdaParam {‘,’ TypeLambdaParam} ‘]’
16+
TypeLambdaParam ::= {Annotation} (id | ‘_’) [TypeParamClause] [‘>:’ Type] [‘<:’ Type]
1417
InfixType ::= CompoundType {id [nl] CompoundType}
1518
CompoundType ::= AnnotType {‘with’ AnnotType} [Refinement]
1619
| Refinement
@@ -453,8 +456,7 @@ Their exact supertype and implementation can be consulted in the [function class
453456

454457
## Non-Value Types
455458

456-
The types explained in the following do not denote sets of values, nor do they appear explicitly in programs.
457-
They are introduced in this report as the internal types of defined identifiers.
459+
The types explained in the following do not denote sets of values.
458460

459461
### Method Types
460462

@@ -511,20 +513,30 @@ union : [A >: Nothing <: Comparable[A]] (x: Set[A], xs: Set[A]) Set[A]
511513

512514
### Type Constructors
513515

514-
A _type constructor_ is represented internally much like a polymorphic method type.
515-
`[´\pm´ ´a_1´ >: ´L_1´ <: ´U_1, ..., \pm a_n´ >: ´L_n´ <: ´U_n´] ´T´` represents a type that is expected by a [type constructor parameter](04-basic-declarations-and-definitions.html#type-parameters) or an [abstract type constructor binding](04-basic-declarations-and-definitions.html#type-declarations-and-type-aliases) with the corresponding type parameter clause.
516+
```
517+
Type ::= ... | TypeLambdaParams ‘=>>’ Type
518+
TypeParamClause ::= ‘[’ TypeParam {‘,’ TypeParam} ‘]’
519+
TypeLambdaParams ::= ‘[’ TypeLambdaParam {‘,’ TypeLambdaParam} ‘]’
520+
TypeLambdaParam ::= {Annotation} (id | ‘_’) [TypeParamClause] [‘>:’ Type] [‘<:’ Type]
521+
```
516522

517-
###### Example
523+
<!-- the definition of a parameterized type above uses the concept of a type constructor, so we can't define a type constructor as an unapplied parameterized type. -->
518524

519-
Consider this fragment of the `Iterable[+X]` class:
525+
A _type constructor_ is either:
526+
- a _type lambda_, of the form `[´\mathit{tps}\,´] =>> ´T´` where `[´\mathit{tps}\,´]` is a type parameter clause `[´a_1´ >: ´L_1´ <: ´U_1, ..., a_n´ >: ´L_n´ <: ´U_n´]` for some ´n \gt 0´ and ´T´ is either a value type
527+
or another type lambda.
528+
- a reference to a [desugared type declaration](04-basic-declarations-and-definitions.html#type-declarations-and-type-aliases) upper-bounded by a type lambda.
529+
- a reference to a [polymorphic class](05-classes-and-objects.html##class-definitions).
520530

521-
```scala
522-
trait Iterable[+X] {
523-
def flatMap[newType[+X] <: Iterable[X], S](f: X => newType[S]): newType[S]
524-
}
525-
```
531+
Each type parameter ´a_i´ of a type lambda has a variance ´v_i´ which cannot be written down by the user but is inferred from the body of the type lambda to maximize the number of types that conform to the type lambda.
532+
<!-- TODO: write down the exact algorithm? -->
526533

527-
Conceptually, the type constructor `Iterable` is a name for the anonymous type `[+X] Iterable[X]`, which may be passed to the `newType` type constructor parameter in `flatMap`.
534+
#### Inferred type parameter clause
535+
536+
To each type constructor corresponds an _inferred type parameter clause_ which is computed as follow:
537+
- For a type lambda, its type parameter clause (including variance annotations).
538+
- For a type declaration upper-bounded by a type lambda ´T´, the inferred clause of ´T´.
539+
- For a polymorphic class, its type parameter clause.
528540

529541
<!-- ### Overloaded Types
530542
@@ -660,6 +672,8 @@ We define the following relations between types.
660672

661673
### Equivalence
662674

675+
´\color{red}{\text{TODO SCALA3: Redefine equivalence as mutual conformance?}}´
676+
663677
Equivalence ´(\equiv)´ between types is the smallest congruence [^congruence] such that the following holds:
664678

665679
- If ´t´ is defined by a type alias `type ´t´ = ´T´`, then ´t´ is equivalent to ´T´.
@@ -708,7 +722,7 @@ The conformance relation ´(<:)´ is the smallest transitive relation that satis
708722
- If ´T_i \equiv T_i'´ for ´i \in \{ 1, ..., n\}´ and ´U´ conforms to ´U'´ then the method type ´(p_1:T_1, ..., p_n:T_n) U´ conforms to ´(p_1':T_1', ..., p_n':T_n') U'´.
709723
- The polymorphic type ´[a_1 >: L_1 <: U_1, ..., a_n >: L_n <: U_n] T´ conforms to the polymorphic type ´[a_1 >: L_1' <: U_1', ..., a_n >: L_n' <: U_n'] T'´ if, assuming ´L_1' <: a_1 <: U_1', ..., L_n' <: a_n <: U_n'´ one has ´T <: T'´ and ´L_i <: L_i'´ and ´U_i' <: U_i´ for ´i \in \{ 1, ..., n \}´.
710724
- Type constructors ´T´ and ´T'´ follow a similar discipline.
711-
We characterize ´T´ and ´T'´ by their type parameter clauses ´[a_1, ..., a_n]´ and ´[a_1', ..., a_n']´, where an ´a_i´ or ´a_i'´ may include a variance annotation, a higher-order type parameter clause, and bounds.
725+
We characterize ´T´ and ´T'´ by their [inferred type parameter clauses](#inferred-type-parameter-clause) ´[a_1, ..., a_n]´ and ´[a_1', ..., a_n']´.
712726
Then, ´T´ conforms to ´T'´ if any list ´[t_1, ..., t_n]´ -- with declared variances, bounds and higher-order type parameter clauses -- of valid type arguments for ´T'´ is also a valid list of type arguments for ´T´ and ´T[t_1, ..., t_n] <: T'[t_1, ..., t_n]´.
713727
Note that this entails that:
714728
- The bounds on ´a_i´ must be weaker than the corresponding bounds declared for ´a'_i´.

docs/_spec/04-basic-declarations-and-definitions.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,54 @@ Def ::= ‘type’ {nl} TypeDef
226226
TypeDef ::= id [TypeParamClause] ‘=’ Type
227227
```
228228

229+
### Desugaring of parameterized type declarations
230+
A parameterized type declaration is desugared into an unparameterized type declaration
231+
whose bounds are type lambdas with explicit variance annotations.
232+
233+
#### Abstract Type
234+
An abstract type
235+
```scala
236+
type ´t´[´\mathit{tps}\,´] >: ´L´ <: ´U´
237+
```
238+
is desugared into an unparameterized abstract type as follow:
239+
- If `L` conforms to `Nothing`, then,
240+
241+
```scala
242+
type ´t´ >: Nothing
243+
<:\mathit{tps'}\,´] =>> ´U´
244+
```
245+
- otherwise,
246+
247+
```scala
248+
type ´t´ >:\mathit{tps'}\,´] =>> ´L´
249+
<:\mathit{tps'}\,´] =>> ´U´
250+
```
251+
252+
If at least one of the ´\mathit{tps}´ contains an explicit variance annotation, then ´\mathit{tps'} = \mathit{tps}´, otherwise we infer the variance of each type parameter as with the user-written type lambda `[´\mathit{tps}\,´] =>> ´U´`.
253+
254+
The same desugaring applies to type parameters. For instance,
255+
```scala
256+
[F[X] <: Coll[X]]
257+
```
258+
is treated as a shorthand for
259+
```scala
260+
[F >: Nothing <: [X] =>> Coll[X]]
261+
```
262+
263+
#### Type Alias
264+
A parameterized type alias
265+
```scala
266+
type ´t´[´\mathit{tps}\,´] = ´T´
267+
```
268+
is desugared into an unparameterized type alias
269+
```scala
270+
type ´t´ =\mathit{tps'}\,´] =>> ´T´
271+
```
272+
where ´\mathit{tps'}´ is computed as in the previous case.
273+
274+
´\color{red}{\text{TODO SCALA3: Everything else in this section (and the next one
275+
on type parameters) needs to be rewritten to take into account the desugaring described above.}}´
276+
229277
A _type declaration_ `type ´t´[´\mathit{tps}\,´] >: ´L´ <: ´U´` declares ´t´ to be an abstract type with lower bound type ´L´ and upper bound type ´U´.
230278
If the type parameter clause `[´\mathit{tps}\,´]` is omitted, ´t´ abstracts over a proper type, otherwise ´t´ stands for a type constructor that accepts type arguments as described by the type parameter clause.
231279

docs/_spec/TODOreference/new-types/type-lambdas.md renamed to docs/_spec/APPLIEDreference/new-types/type-lambdas.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,3 @@ a type definition.
1313

1414
For instance, the type above defines a binary type constructor, which maps arguments `X` and `Y` to `Map[Y, X]`.
1515
Type parameters of type lambdas can have bounds, but they cannot carry `+` or `-` variance annotations.
16-
17-
[More details](./type-lambdas-spec.md)

docs/_spec/TODOreference/new-types/type-lambdas-spec.md

Lines changed: 0 additions & 116 deletions
This file was deleted.

0 commit comments

Comments
 (0)