Skip to content

Commit addf780

Browse files
committed
Scribble example w/migrating contracts and contract types
Still missing good examples for the binary contract types
1 parent 53b993a commit addf780

File tree

1 file changed

+82
-8
lines changed

1 file changed

+82
-8
lines changed

typed-racket-doc/typed-racket/scribblings/reference/typed-contracts.scrbl

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,84 @@
1414
@defmodule[typed/racket/contract]
1515

1616
Typed Racket supports contract programming using the
17-
@racketmodname[racket/contract] library. This section covers the
18-
contract-specific features of the type system as well as the functionality
19-
currently supported in Typed Racket.
17+
@racketmodname[racket/contract] library. For Racket programmers that
18+
want to migrate a module and its contracts to Typed Racket, the first
19+
section walks through that process. That example also serves to
20+
introduce some of the contract-specific features in the type system.
21+
22+
The remaining sections give more detail about the type system and
23+
document support for Racket's contract library.
24+
25+
@section{Introduction: Migrating a Racket module's contracts}
26+
27+
The function @racket[g] in this Racket module is provided to clients
28+
with a contract
29+
@;contract adapted from the intro of Findler, Felleisen 2002
30+
@racketmod[racket
31+
(provide
32+
(contract-out
33+
[g (-> (-> (and/c exact-integer? (>/c 9))
34+
(and/c exact-integer? (between/c 0 99)))
35+
(and/c exact-integer? (between/c 0 99)))]))
36+
(define (g proc)
37+
@#,(elem "..."))]
38+
39+
Clients must call @racket[g] with a procedure, and when that procedure
40+
is called with an integer larger than 9 it must return an integer
41+
between 0 and 99. Given such a procedure, @racket[g] itself must
42+
return an integer between 0 and 99, too. If any of the requirements
43+
aren't upheld, an error is raised, identifying where and when the
44+
requirement was broken.
45+
46+
Programmers can migrate their module and its contracts to Typed
47+
Racket. A typed version of the previous example might look like
48+
@racketmod[typed/racket
49+
(provide
50+
(contract-out
51+
[g (->/c (->/c (and/c exact-integer? (>/c 9))
52+
(and/c exact-integer? (between/c 0 99)))
53+
(and/c exact-integer? (between/c 0 99)))]))
54+
(: g (-> (-> Integer Integer) Integer))
55+
(define (g proc)
56+
@#,(elem "..."))]
57+
58+
Typed Racket's type system makes some of these contracts redundant.
59+
All of the @racket[exact-integer?] contracts, for example, are implied
60+
by @racket[g]'s type. So let's replace the whole @racket[->/c]
61+
contract with the following simpler one
62+
@racketblock[(->/c (->/c (>/c 9) (between/c 0 99))
63+
(between/c 0 99))]
64+
65+
Before digging into how the type system allows us to replace the first
66+
contract with the second one, let's briefly talk about contracts and
67+
their types.
68+
69+
Because arbitrary (typed) functions can be used as part of a contract
70+
in Typed Racket, contract types ensure that that function's type
71+
requirements aren't violated. If the @racket[even?] function is used
72+
as a contract, for example, its contract type guarantees that it will
73+
only be applied to @racket[Integers]. If the contract system didn't
74+
have higher-order contracts, then something similar to function types
75+
would likely be sufficient to ensure that @racket[even?] wasn't
76+
misused. Higher-order contracts, though, need an extended type
77+
system that treats contract application different from function
78+
application.
79+
80+
The type of the first contract is
81+
@ex[#:label #f
82+
(->/c (->/c (and/c exact-integer? (>/c 9))
83+
(and/c exact-integer? (between/c 0 99)))
84+
(and/c exact-integer? (between/c 0 99)))]
85+
while the type of the second contract is
86+
@ex[#:label #f
87+
(->/c (->/c (>/c 9) (between/c 0 99))
88+
(between/c 0 99))]
2089

2190
@section{Types}
2291

92+
As shown in the introduction, adding types to Racket's higher-order
93+
contracts requires extending Typed Racket with new kinds of types.
94+
2395
@defform[#:kind "type"
2496
(Contract [in type] [out type])]{
2597
A contract can only be attached to values that satisfy its @racket[in] type,
@@ -30,19 +102,21 @@ currently supported in Typed Racket.
30102

31103
The result's type is a lower-bound of @racket[out] and @racket[t] with respect
32104
to the precision order, which is like the subtype order. It differs in that it
33-
lacks contravariance in negative positions such as function domains.
105+
lacks contravariance in negative positions such as function domains. As odd as
106+
this may sound, it's OK for the same reason that Typed Racket can cast a
107+
function from @racket[(-> Integer Integer)] to @racket[(-> Natural Natural)].
34108

35-
@racket[Contract] is the most general type for contracts.
109+
@racket[Contract] is the most general type constructor for contracts.
36110
}
37111

38112
@defform[#:kind "type"
39113
(FlatContract [in type] [out type])]{
40114
This type is like @racket[Contract] but corresponds to @tech{flat contracts}. All
41-
@racket[FlatCon] contracts have a corresponding @racket[Contract] type. For
115+
@racket[FlatContract] have a corresponding @racket[Contract] type. For
42116
example, a @racket[(FlatContract Real Real)] is also a @racket[(Contract Real Real)].
43117

44-
A contract with @racket[FlatCon] type can be used as a function having domain
45-
type @racket[in].
118+
A contract with @racket[FlatContract] type can be used as a function
119+
having domain type @racket[in].
46120

47121
Ordinary Racket @tech[#:key "contracts"]{values coercible to a contract}, such
48122
as integers, do not have this type. Coercing such values of type @racket[T] to

0 commit comments

Comments
 (0)