|
6 | 6 |
|
7 | 7 | @(define the-eval (make-base-eval))
|
8 | 8 | @(the-eval '(require typed/racket))
|
| 9 | +@(define the-eval* (make-base-eval)) |
| 10 | +@(the-eval* '(require typed/racket)) |
9 | 11 |
|
10 | 12 | @title[#:tag "occurrence-typing"]{Occurrence Typing}
|
11 | 13 |
|
@@ -84,6 +86,51 @@ the typechecker learns from the result of applying the function:
|
84 | 86 | Predicates for all built-in types are annotated with similar propositions
|
85 | 87 | that allow the type system to reason logically about predicate checks.
|
86 | 88 |
|
| 89 | +@subsection{Specifying Propositions} |
| 90 | + |
| 91 | +While propositions are provided for all built-in type predicates, |
| 92 | +we may want to provide propositions for our own predicates as well. |
| 93 | +For instance, consider the following predicate, |
| 94 | +which determines whether a given list contains only strings. |
| 95 | +Intuitively, a value that satisfies the predicate must have type |
| 96 | +@racket[(Listof String)]. |
| 97 | + |
| 98 | +@examples[#:no-result #:eval the-eval* |
| 99 | + (: listof-string? (-> (Listof Any) Boolean)) |
| 100 | + (define (listof-string? lst) |
| 101 | + (andmap string? lst)) |
| 102 | +] |
| 103 | + |
| 104 | +We then may wish to use this predicate to narrow a type in our main program: |
| 105 | + |
| 106 | +@examples[#:label #f #:eval the-eval* |
| 107 | + (: main (-> (Listof Any) String)) |
| 108 | + (eval:error (define (main lst) |
| 109 | + (cond |
| 110 | + [(listof-string? lst) (first lst)] |
| 111 | + [else "not a list of strings"]))) |
| 112 | +] |
| 113 | + |
| 114 | +Unfortunately, Typed Racket fails to narrow the type, because we did not specify |
| 115 | +a proposition for @racket[listof-string?]. To fix this issue, we include |
| 116 | +the proposition in the @racket[->] form for @racket[listof-string]. |
| 117 | + |
| 118 | +@examples[#:no-result #:eval the-eval |
| 119 | + (: listof-string? (-> (Listof Any) Boolean : (Listof String))) |
| 120 | + (define (listof-string? lst) |
| 121 | + (andmap string? lst)) |
| 122 | +] |
| 123 | + |
| 124 | +With the proposition, Typed Racket successfully type-checks our main program. |
| 125 | + |
| 126 | +@examples[#:label #f #:eval the-eval |
| 127 | + (: main (-> (Listof Any) String)) |
| 128 | + (define (main lst) |
| 129 | + (cond |
| 130 | + [(listof-string? lst) (first lst)] |
| 131 | + [else "not a list of strings"])) |
| 132 | +] |
| 133 | + |
87 | 134 | @subsection{One-sided Propositions}
|
88 | 135 |
|
89 | 136 | Sometimes, a predicate may provide information when it
|
|
0 commit comments