Skip to content

Commit 5ff3adf

Browse files
committed
changes
- add explicit subsections - expand more on checking #:methods - add checking method application
1 parent 939c36f commit 5ff3adf

File tree

1 file changed

+47
-8
lines changed

1 file changed

+47
-8
lines changed

rfcs/text/0003-typing-generic-interfaces.md

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,19 @@ which has been one of the most wanted features.
1313

1414

1515
# Guide-level explanation
16-
There are two parts of the proposal: First, we address typing declarations of
16+
There are three parts of the proposal: First, we address typing declarations of
1717
generic interfaces. Then, we show how the type checker checks structs' method
18-
definitions.
18+
definitions. Lastly, we present how type checking method application works.
1919

20+
## Declaration of typed generic inferfaces.
2021
To annotate a generic interface, we introduce a typed counterpart for
2122
`define/generics`.
2223

2324
```racket
2425
(define-generics showable
2526
(: gen-show (showable . -> . String) )
2627
(gen-show showable)
27-
(: gen-show2 (showable showable . -> . String) )
28+
(: gen-show2 (String showable . -> . String) )
2829
(gen-show2 some-b showable)
2930
#:defined-predicate tpred ;; (: tpred (-> showable (U 'gen-show 'gen-show2) * Boolean)). Note: No need to generate contracts
3031
#:defaults
@@ -69,8 +70,11 @@ cannot tell which argument would act as the specializer based on the type of
6970
- produce a typed immutable hash table that is assigned to `defined-table-id`
7071
when it is specified. The table's keys have a union type, `(U
7172
method-id-as-symbol ...)`, and values are simply booleans.
73+
- produce the type predicate `showable?`, a similar to other fellow predicates in TR,
74+
has type `(-> Any Boolean : showable)`
7275
- #:derive-property, TODO
7376

77+
## Typed method specialization
7478
For method implementation in a struct's definition, the typechecking process is
7579
also straightforward
7680

@@ -86,13 +90,40 @@ also straightforward
8690
)
8791
```
8892

89-
First, the typechecker ensures every `method-id` in a `#:methods` specification
90-
is well scoped. Then it checks if the specializer argument's and return type
91-
are covariant and if the rest are contraviant. `define/generic` makes the local
92-
id `super-show` have the same type of `gen-show`, namely `(-> showable String)`.
93+
For any structure that implemented generice interfaces, first the typechecker
94+
ensures every `interface-id` in a `#:methods` specification is well scoped. It
95+
then checks if every method of `interface-id` is implemented. There are 3
96+
possibilities of a method to be considered implemented:
97+
98+
1. The method is defined in the `#:methods` specification. Then it checks if the
99+
specializer and return type are covariant and if the rest are contraviant.
100+
`define/generic` makes the local id `super-show` have the same type of
101+
`gen-show`, namely `(-> showable String)`.
102+
2. The interface includes a well-typed fallback implementation for the method.
103+
3. In either `#:defaults` or `#:fast-defaults`, there is a type predicate for
104+
`T` such that T is a super type of the current structure type.
105+
106+
Note that under the proposed rules, all methods of a generic interface must be
107+
implemented, which is different from that in Racket. Consider the following code:
108+
109+
```
110+
(struct fruit (name)
111+
#:methods gen:showable
112+
[(define (gen-show me)
113+
(format "~a" (fruit-name me)))])
114+
115+
(let ([a (fruit "apple")])
116+
(when (showable? a)
117+
(gen-show2 'whatever a)))
118+
```
119+
120+
Racket recognizes a `fruit` instance showable, despite that `fruit` lacks
121+
implementation of `gen-show2`. Then a subsequent call `gen-show2` on that
122+
instance raises a run-time error. However, TR should reject the program above.
123+
93124

94125
Though Racket doesn't support subclass or inheritance between generic
95-
interfaces, we can still express constraints using types in `define/generics`.
126+
interfaces, we can still express constraints using types in `define-generics`.
96127

97128
```
98129
(define-generics eq-able
@@ -145,6 +176,14 @@ because an `Dummy` instance breaks the contract of `gen-/=`.
145176
However, the typechecker simply rejects the code. Since `Dummy` does not
146177
implement `gen:eq-able`, it is not of a subtype of `(Intersection eq-able ord-able)`
147178

179+
## Typechecking Generic Method Application
180+
The typechecker checks calls to a generic method in the same fashion as it does
181+
to a plain function. Every argument type is checked against the by-position
182+
parameter type of the method described in its interface definition. For example,
183+
when checking `(gen-show2 b a)`, the typechecker checks if `a` is of a subtype
184+
of `showable` and `b` is of a subtype of `String`.
185+
186+
148187
# Reference-level explanation
149188
Add a new prim for `define-generics` that supports the features mentioned in the
150189
Guide-level explanation.

0 commit comments

Comments
 (0)