The Typed Racket Reference
#lang typed/racket/base |
#lang typed/racket |
1 Type Reference
1.1 Base Types
1.1.1 Numeric Types
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
Examples: |
> 7 |
- : Positive-Fixnum |
7 |
> 8.3 |
- : Nonnegative-Float |
8.3 |
> (/ 8 3) |
- : Exact-Rational |
8/3 |
> 0 |
- : Zero |
0 |
> -12 |
- : Negative-Fixnum |
-12 |
> 3+4i |
- : Number |
3+4i |
1.1.2 Other Base Types
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
Examples: |
> #t |
- : True |
#t |
> #f |
> "hello" |
"hello" |
> (current-input-port) |
- : Input-Port |
#<input-port:string> |
> (current-output-port) |
- : Output-Port |
#<output-port:string> |
> (string->path "/") |
- : Path |
#<path:/> |
> #rx"a*b*" |
- : Regexp |
#rx"a*b*" |
> #px"a*b*" |
- : Regexp |
#px"a*b*" |
> '#"bytes" |
- : Bytes |
#"bytes" |
> (current-namespace) |
- : Namespace |
#<namespace:0> |
> #\b |
- : Char |
#\b |
> (thread (lambda () (add1 7))) |
- : Thread |
#<thread> |
1.2 Singleton Types
Some kinds of data are given singleton types by default. In particular, symbols and keywords have types which consist only of the particular symbol or keyword. These types are subtypes of Symbol and Keyword, respectively.
Examples: |
> '#:foo |
- : #:foo |
'#:foo |
> 'bar |
- : 'bar |
'bar |
1.3 Containers
The following base types are parameteric in their type arguments.
(Pair s t) |
Examples: |
> (cons 1 2) |
- : (Pairof Positive-Fixnum Positive-Fixnum) |
'(1 . 2) |
> (cons 1 "one") |
- : (Pairof Positive-Fixnum String) |
'(1 . "one") |
(Listof t) |
(List t ...) |
(List t ... trest ... bound) |
Examples: |
> (list 'a 'b 'c) |
- : (List 'a 'b 'c) |
'(a b c) |
> (map symbol->string (list 'a 'b 'c)) |
- : (Pairof String (Listof String)) |
'("a" "b" "c") |
(Boxof t) |
Example: |
> (box "hello world") |
- : (Boxof String) |
'#&"hello world" |
Example: |
> #'here |
- : (Syntaxof 'here) |
#<syntax:26:0 here> |
(Vectorof t) |
(Vector t ...) |
Examples: |
> (vector 1 2 3) |
- : (Vector Integer Integer Integer) |
'#(1 2 3) |
> #(a b c) |
- : (Vector Symbol Symbol Symbol) |
'#(a b c) |
(HashTable k v) |
Example: |
> #hash((a . 1) (b . 2)) |
- : (HashTable Symbol Integer) |
'#hash((b . 2) (a . 1)) |
(Channelof t) |
Example: |
> (ann (make-channel) (Channelof Symbol)) |
- : (Channelof Symbol) |
#<channel> |
(Parameterof t) |
(Parameterof s t) |
Examples: |
> current-input-port |
- : (Parameterof Input-Port) |
#<procedure:current-input-port> |
> current-directory |
- : (Parameterof Path-String Path) |
#<procedure:current-directory> |
(Promise t) |
Example: |
> (delay 3) |
- : (Promise Positive-Fixnum) |
#<promise:eval:33:0> |
1.4 Other Type Constructors
(dom ... -> rng) |
(dom ... rest * -> rng) |
(dom ... rest ... bound -> rng) |
(dom -> rng : pred) |
Examples: |
> (λ: ([x : Number]) x) |
- : (Number -> Number : ((! False @ 0) | (False @ 0)) (0)) |
#<procedure> |
> (λ: ([x : Number] y : String *) (length y)) |
- : (Number String * -> Nonnegative-Fixnum) |
#<procedure> |
> ormap |
- : (All (a c b ...) ((a b ... b -> c) (Listof a) (Listof b) ... b -> c)) |
#<procedure:ormap> |
> string? |
- : (Any -> Boolean : String) |
#<procedure:string?> |
(U t ...) |
Example: |
> (λ: ([x : Real])(if (> 0 x) "yes" 'no)) |
- : (Real -> (U String 'no) : (Top | Bot)) |
#<procedure> |
(case-lambda fun-ty ...) |
(t t1 t2 ...) |
(All (v ...) t) |
(values t ...) |
Example: |
> (values 1 2 3) |
- : (Values Positive-Fixnum Positive-Fixnum Positive-Fixnum) |
1 |
2 |
3 |
v |
(quote val) |
i |
(Rec n t) |
1.5 Other Types
(Option t) |
2 Special Form Reference
Typed Racket provides a variety of special forms above and beyond those in Racket. They are used for annotating variables with types, creating new types, and annotating expressions.
2.1 Binding Forms
loop, f, a, and v are names, t is a type. e is an expression and body is a block.
| |
| |
| |
| |
|
2.2 Anonymous Functions
(lambda: formals . body) | |||||||||||||||
|
(λ: formals . body) |
(plambda: (a ...) formals . body) |
(case-lambda: [formals body] ...) |
(pcase-lambda: (a ...) [formals body] ...) |
(opt-lambda: formals . body) | |||||||||||||||
|
(popt-lambda: (a ...) formals . body) |
2.3 Loops
| |||||||||||||||||||||||||||||||
|
| ||||
|
| ||||
| ||||
|
| |||||||||||
|
2.4 Definitions
2.5 Structure Definitions
(struct: maybe-type-vars name-spec ([f : t] ...) options ...) | |||||||||||||||||||||||||||||||||||||||||
|
Options provided have the same meaning as for the struct form.
(define-struct: maybe-type-vars name-spec ([f : t] ...) options ...) | |||||||||||||||||||||||||||||||||||||||||
|
(define-struct/exec: name-spec ([f : t] ...) [e : proc-t]) | ||||||||||
|
2.6 Names for Types
(define-type name t) |
(define-type (name v ...) t) |
2.7 Generating Predicates Automatically
(define-predicate name t) |
2.8 Type Annotation and Instantiation
(: v t) |
(provide: [v t] ...) |
#{v : t} This declares that the variable v has type t. This is legal only for binding occurences of v.
(ann e t) |
#{e :: t} This is identical to (ann e t).
(inst e t ...) |
#{e @ t ...} This is identical to (inst e t ...).
2.9 Require
Here, m is a module spec, pred is an identifier naming a predicate, and r is an optionally-renamed identifier.
(require/typed m rt-clause ...) | ||||||||||||||||||||
|
The first form requires r, giving it type t.
The second and third forms require the struct with name name with fields f ..., where each field has type t. The third form allows a parent structure type to be specified. The parent type must already be a structure type known to Typed Racket, either built-in or via require/typed. The structure predicate has the appropriate Typed Racket filter type so that it may be used as a predicate in if expressions in Typed Racket.
The fourth case defines a new type t. pred, imported from module m, is a predicate for this type. The type is defined as precisely those values to which pred produces #t. pred must have type (Any -> Boolean). Opaque types must be required lexically before they are used.
In all cases, the identifiers are protected with contracts which enforce the specified types. If this contract fails, the module m is blamed.
Some types, notably polymorphic types constructed with All, cannot be converted to contracts and raise a static error when used in a require/typed form.
3 Libraries Provided With Typed Racket
The typed/racket language corresponds to the
racket language—
#lang typed/racket |
(modulo 12 2) |
The typed/racket/base language corresponds to the racket/base language.
Some libraries have counterparts in the typed collection, which provide the same exports as the untyped versions. Such libraries include srfi/14, net/url, and many others.
#lang typed/racket |
(require typed/srfi/14) |
(char-set= (string->char-set "hello") |
(string->char-set "olleh")) |
To participate in making more libraries available, please visit here.
Other libraries can be used with Typed Racket via require/typed.
#lang typed/racket |
(require/typed version/check |
[check-version (-> (U Symbol (Listof Any)))]) |
(check-version) |
4 Utilities
Typed Racket provides some additional utility functions to facilitate typed programming.
Examples: |
> (define: x : (U #f Number) (string->number "7")) |
> x |
- : (U Number False) |
7 |
> (assert x) |
- : Number |
7 |
> (define: y : (U String Number) 0) |
> y |
- : (U String Number) |
0 |
> (assert y number?) |
- : Number |
0 |
> (assert y boolean?) |
Assertion failed |
(with-asserts ([id maybe-pred] ...) body ...+) | |||||||||||
|
5 Typed Racket Syntax Without Type Checking
#lang typed/racket/no-check |
#lang typed/racket/base/no-check |
On occasions where the Typed Racket syntax is useful, but actual typechecking is not desired, the typed/racket/no-check and typed/racket/base/no-check languages are useful. They provide the same bindings and syntax as typed/racket and typed/racket/base, but do no type checking.
Examples:
#lang typed/racket/no-check |
(: x Number) |
(define x "not-a-number") |
6 Typed Regions
The with-type for allows for localized Typed Racket regions in otherwise untyped code.
(with-type result-spec fv-clause body ...+) | |||||||||||||||||||||||||||||||
(with-type export-spec fv-clause body ...+) | |||||||||||||||||||||||||||||||
|
The second form, which can be used as a definition, checks that each of the export-ids has the specified type. These types are also enforced in the surrounding code with contracts.
The ids are assumed to have the types ascribed to them; these types are converted to contracts and checked dynamically.
Examples: | ||||
> (with-type #:result Number 3) | ||||
3 | ||||
| ||||
contract violation: expected <Number>, given: #f | ||||
contract from (region typed-region) via (region | ||||
typed-region), blaming top-level | ||||
contract: (-> Number Number) | ||||
| ||||
"hello, world" | ||||
| ||||
self-contract violation: expected <String>, given: 'hello | ||||
contract on x from top-level, blaming top-level | ||||
contract: String | ||||
at: eval:5.0 | ||||
| ||||
> (fun val) | ||||
17 |
7 Optimization in Typed Racket
See Optimization in Typed Racket in the guide for tips to get the most out of the optimizer.
Typed Racket provides a type-driven optimizer that rewrites well-typed programs to potentially make them faster. It should in no way make your programs slower or unsafe.
Typed Racket’s optimizer is turned on by default. If you want to deactivate it (for debugging, for instance), you must add the #:no-optimize keyword when specifying the language of your program:
#lang typed/racket #:no-optimize
8 Legacy Forms
The following forms are provided by Typed Racket for backwards compatibility.