Skip to content

Commit d1ba049

Browse files
authored
[Docs] Add section on custom propositions (#1345)
* Add section on custom propositions
1 parent 351c383 commit d1ba049

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

typed-racket-doc/typed-racket/scribblings/guide/occurrence.scrbl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
@(define the-eval (make-base-eval))
88
@(the-eval '(require typed/racket))
9+
@(define the-eval* (make-base-eval))
10+
@(the-eval* '(require typed/racket))
911

1012
@title[#:tag "occurrence-typing"]{Occurrence Typing}
1113

@@ -84,6 +86,51 @@ the typechecker learns from the result of applying the function:
8486
Predicates for all built-in types are annotated with similar propositions
8587
that allow the type system to reason logically about predicate checks.
8688

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+
87134
@subsection{One-sided Propositions}
88135

89136
Sometimes, a predicate may provide information when it

0 commit comments

Comments
 (0)