type-expander.scrbl (30821B)
1 #lang scribble/manual 2 3 @title{Type expander library} 4 @author{@author+email["Suzanne Soy" "racket@suzanne.soy"]} 5 6 @defmodule[type-expander 7 #:use-sources [(lib "type-expander/type-expander.hl.rkt") 8 (lib "type-expander/more-expanders.hl.rkt")]] 9 10 @require[racket/require 11 scribble/example 12 @for-syntax[racket/base] 13 @for-label[type-expander 14 type-expander/expander 15 (subtract-in typed/racket/base 16 type-expander 17 type-expander/expander) 18 (only-in racket/base [... …]) 19 (prefix-in racket/base: racket/base) 20 syntax/stx 21 racket/list 22 syntax/parse 23 syntax/parse/experimental/template 24 auto-syntax-e 25 debug-scopes]] 26 27 @(require (for-syntax syntax/strip-context 28 syntax/stx 29 racket/syntax)) 30 @(define-syntax (orig stx) 31 (syntax-case stx () 32 [(_ name ...) 33 (with-syntax ([(prefixed ...) 34 (stx-map (λ (id) (format-id id "orig:~a" id)) 35 #'(name ...))]) 36 #`(begin 37 (module #,(syntax-local-introduce #'orig-module) . 38 #,(strip-context 39 #'(racket/base 40 (require (for-label (only-meta-in 0 (only-in typed/racket 41 name ...)))) 42 (require scribble/manual) 43 (define prefixed @racket[name]) ... 44 (provide prefixed ...)))) 45 (require #,(syntax-local-introduce #''orig-module))))])) 46 47 @(orig 48 class 49 ;; 50 define-type 51 ;; TODO: add all-defined-out in prims.rkt 52 ;; top-interaction.rkt 53 :type 54 :print-type 55 :query-type/args 56 :query-type/result 57 ;; case-lambda.rkt 58 case-lambda 59 case-lambda: 60 pcase-lambda: 61 ;; (submod "prims-contract.rkt" forms) 62 require/opaque-type 63 ;require-typed-struct-legacy 64 require-typed-struct 65 ;require/typed-legacy 66 require/typed 67 require/typed/provide 68 require-typed-struct/provide 69 cast 70 make-predicate 71 define-predicate 72 ;; prims.rkt 73 define-type-alias 74 define-new-subtype 75 define-typed-struct 76 define-typed-struct/exec 77 ann 78 inst 79 : 80 define-struct: 81 define-struct 82 struct 83 struct: 84 λ: 85 lambda: 86 lambda 87 λ 88 define 89 let 90 let* 91 letrec 92 let-values 93 letrec-values 94 let/cc 95 let/ec 96 let: 97 let*: 98 letrec: 99 let-values: 100 letrec-values: 101 let/cc: 102 let/ec: 103 for 104 for/list 105 for/vector 106 for/hash 107 for/hasheq 108 for/hasheqv 109 for/and 110 for/or 111 for/sum 112 for/product 113 for/lists 114 for/first 115 for/last 116 for/fold 117 for* 118 for*/list 119 for*/lists 120 for*/vector 121 for*/hash 122 for*/hasheq 123 for*/hasheqv 124 for*/and 125 for*/or 126 for*/sum 127 for*/product 128 for*/first 129 for*/last 130 for*/fold 131 for/set 132 for*/set 133 do 134 do: 135 with-handlers 136 define-struct/exec: 137 define-struct/exec) 138 139 @(define eval-factory 140 (make-eval-factory (list 'typed/racket 'type-expander))) 141 142 This library is implemented using literate programming. The 143 implementation details are presented in the 144 @other-doc['(lib 145 "type-expander/scribblings/type-expander-implementation.scrbl")] 146 document. 147 148 It enhances @racketmodname[typed/racket] with 149 @deftech[#:key "type expander"]{type expanders}, which are 150 special macros that can appear wherever a regular type is 151 usually expected, and must expand to a type. Type expanders 152 are to types what 153 @tech[#:doc '(lib "scribblings/reference/reference.scrbl") 154 #:key "match expander"]{ 155 match expanders} are to @racket[match] patterns. 156 157 It is based on 158 @hyperlink[(string-append "https://github.com/racket/racket/compare/" 159 "master...takikawa:tr-type-expander")]{ 160 Asumu Takikawa's type expanders} (see also his 161 @hyperlink["https://github.com/racket/racket/pull/604"]{original pull request}). 162 Asumu Takikawa's work attempted to integrate type expanders 163 directly into Typed/Racket. This project instead implements 164 type expanders as a library, which does not need any changes 165 to the core Typed/Racket codebase. This shows the 166 extensibility of Typed/Racket thanks to macros, and could 167 serve as the basis for other projects which need to alter 168 how Typed/Racket handles types. 169 170 The input for a type expander is the syntax used to call 171 it, just as the input to a macro is the syntax used to call 172 it. The output should be a type, which can itself contain 173 type expanders. 174 175 This library works by shadowing the definitions of 176 @orig::, @orig:define, @orig:lambda @etc from 177 @racketmodname[typed/racket] with versions which support 178 type expanders. 179 180 @section{@(hash-lang) and module languages based on 181 @racketmodname[type-expander]} 182 183 @subsection{@(hash-lang) combining @racketmodname[type-expander] and 184 @racketmodname[typed/racket]} 185 186 @defmodulelang[type-expander 187 #:link-target? #f]{ 188 The @racket[#,(hash-lang) #,(racketmodname type-expander)] language works like 189 @racket[#,(hash-lang) #,(racketmodname typed/racket)], but it initially imports 190 the forms overridden by @racketmodname[type-expander], instead of importing 191 the original identifiers defined by @racket[typed/racket]. 192 193 This language cannot be used as a module language, instead use 194 @racketmodname[type-expander/lang] which provides the same bindings.} 195 196 @subsection{Module language combining @racketmodname[type-expander] and 197 @racketmodname[typed/racket]} 198 199 @defmodulelang[type-expander/lang]{ 200 This language is equivalent to 201 @racket[#,(hash-lang) #,(racketmodname type-expander)], but can also be used as 202 a module language.} 203 204 @subsection{@(hash-lang) and module language combining 205 @racketmodname[type-expander] and @racketmodname[typed/racket/base]} 206 207 @defmodulelang[type-expander/base]{ 208 This language is similar to @racketmodname[type-expander/lang], but it 209 exports the identifiers from @racketmodname[typed/racket/base] instead of 210 @racket[typed/racket].} 211 212 213 @section{Defining new type expanders} 214 215 @defform*[((define-type-expander (name stx) . body) 216 (define-type-expander name transformer-function)) 217 #:grammar ([name Identifier] 218 [stx Identifier] 219 [transformer-function (expr/c (-> syntax? syntax?))])]{ 220 The @racket[define-type-expander] form binds 221 @racket[_name] to a type expander, which can be used in 222 places where a type would normally be expected. 223 224 For example, one could define the @racket[HomogeneousList] 225 type expander, which accepts a type @racket[_t] and an 226 integer @racket[_n], and produces a @racket[List] type with 227 @racket[_n] elements, each of type @racket[_t]: 228 229 @racketblock[ 230 (define-type-expander (HomogeneousList stx) 231 (syntax-case stx () 232 [(_ t n) 233 (number? (syntax-e #'n)) 234 (with-syntax ([(tᵢ ...) (stx-map (const #'t) 235 (range (syntax-e #'n)))]) 236 #'(List tᵢ ...))]))]} 237 238 @subsection{Attaching type expanders to existing identifiers} 239 240 @defform[(patch-type-expander name transformer-function) 241 #:grammar ([name Identifier] 242 [transformer-function (expr/c (-> syntax? syntax?))])]{ 243 This macro records in a global table that @racket[name] should behave 244 according to the given @racket[transformer-function], when used as a type. 245 246 It allows attaching type expanders to existing identifiers, without shadowing 247 them. It is used for example to attach the type expanders for @racket[quote], 248 @racket[quasiquote], @racket[syntax] and @racket[quasisyntax] which are 249 described below, and also for the @racket[curry] type expander.} 250 251 @section{Using a type expander} 252 253 The @racket[HomogeneousList] type expander defined above could be 254 used in many of @racketmodname[typed/racket]'s forms. 255 256 @racketblock[ 257 (define-type three-ints (HomogeneousList 3 Integer)) 258 (define (incr3 [x : three-ints]) : (HomogeneousList 3 Integer) 259 (map add1 x)) 260 (ann (incr3 '(1 2 3)) (HomogeneousList 3 Integer))] 261 262 Type expanders can produce types which may contain other 263 uses of type expanders, much in the same way as macros can 264 expand to code calling other macros. The type expander can 265 also produce directly a call to another type expander, just 266 as a macro can expand to a call to another macro, without 267 any extra surrounding syntax. 268 269 @; TODO: examples 270 271 Contrarily to macros, if a call to a type expander is in the 272 first position of more arguments, then the nested call is 273 first expanded, and can produce the name of a second 274 expander which will use the outer arguments, or can simply 275 produce a polymorphic type which will be applied to the 276 arguments. More than two levels of nesting are possible. 277 278 @; TODO: examples with two levels and more. 279 280 @section{Debugging type expanders} 281 282 @defform*[[(debug-type-expander #t) 283 (debug-type-expander #f)]]{ 284 The first form enables printing of debugging information while expanding 285 types, and the second form disables that behaviour. Debugging information is 286 not printed by default. 287 288 Currently, when debugging information is enabled, the type expander prints at 289 each step a human-readable representation of the syntax object it is about to 290 expand, and once an expansion step finishes, it prints the original syntax 291 object as well as its expanded form. The identifiers are adorned with 292 superscripts indicating the scopes present on them. See the documentation for 293 the debugging tool @racket[+scopes] for more details.} 294 295 @section{Compile-time aspects of type expanders} 296 297 @defmodule[type-expander/expander 298 #:use-sources 299 [(submod (lib "type-expander/type-expander.hl.rkt") expander) 300 (submod (lib "type-expander/type-expander.hl.rkt") main)]] 301 302 @defproc[(expand-type [stx Type]) PlainType]{ 303 Fully expands the type @racket[stx], which may contain any 304 number of calls to type expanders. If those calls result in 305 more type expanders, those are expanded too.} 306 307 @defproc[(apply-type-expander [type-expander-stx Identifier] [stx Syntax]) 308 Type]{ 309 Produces the result of applying the type expander bound to 310 @racket[type-expander-stx] to the syntax @racket[stx]. 311 Normally, the syntax @racket[stx] would be of the form 312 @racket[(type-expander-stx arg …)] (similar to a macro 313 call) or simply @racket[type-expander-stx] (similar to an 314 @tech[#:doc '(lib 315 "scribblings/guide/guide.scrbl")]{identifier 316 macro}). It is however possible to pass arbitrary syntax 317 to the type expander, just as it is possible for macros 318 (for example @racket[set!] calls 319 @tech[#:doc '(lib "scribblings/reference/reference.scrbl")]{ 320 assignment transformer} macros with the syntax 321 @racket[(set! macro-name arg …)] as an argument).} 322 323 @deftogether[ 324 (@defthing[prop:type-expander 325 (struct-type-property/c 326 (or/c exact-positive-integer? 327 (→ prop:type-expander? any/c any/c) 328 (→ any/c any/c)))] 329 @defproc[(prop:type-expander? [v any/c]) boolean?] 330 @defproc[(prop:type-expander-ref [v prop:type-expander?]) any/c])]{ 331 A 332 @tech[#:doc '(lib "scribblings/reference/reference.scrbl")]{ 333 structure type property} to identify structure types that 334 act as @tech[#:key "type expander"]{type expanders} like 335 the ones created by @racket[define-type-expander]. 336 337 The property value must be a procedure of arity 1 or 2, or an 338 @racket[exact-nonnegative-integer?] designating a field index within the 339 structure which contains such a procedure. If the procedure's arity includes 340 2, then the first argument is the structure itself (which satisfies 341 @racket[prop:type-expander?]), and the second argument is the syntax object to 342 transform. Otherwise, the single argument is the syntax object to transform. 343 344 The procedure serves as a syntax transformer when 345 expanding the use of a type expander. If the type expander 346 was in the first position of a syntax list (i.e. it looks 347 like a macro or function call), then the whole syntax list 348 is passed as an argument. Otherwise, just the identifier is 349 passed as an argument, exactly as what would be done when 350 calling an 351 @tech[#:doc '(lib 352 "scribblings/guide/guide.scrbl")]{identifier macro}. The 353 procedure can support other use patterns if desired, so 354 that it would be possible in principle to implement special 355 type forms that behave in a way similar to 356 @secref["set__Transformers" #:doc '(lib "scribblings/guide/guide.scrbl")].} 357 358 @subsection{Syntax class for @racketid[:]} 359 360 @defidform[#:kind "syntax-parse syntax class" 361 colon]{ 362 This library shadows the @orig:: identifier from 363 @racketmodname[typed/racket] with a new definition 364 @racket[:], adjusted to handle type expanders. Programs 365 using the @racketmodname[type-expander] library will 366 therefore use our version of @racket[:]. The @racket[:] 367 identifier provided by this library is not 368 @racket[free-identifier=?] with the original @orig:: from 369 @racketmodname[typed/racket]. This has an impact when 370 writing patterns for the @racketmodname[syntax/parse] 371 library, as the two identifiers @racket[:] and @orig:: are 372 not the same from the point of view of the 373 @racket[~literal] pattern. 374 375 The @racket[colon] syntax class is provided 376 @racket[for-syntax] by this library, and can be used in 377 @racket[syntax-parse] patterns, using @racket[c:colon] for 378 example. It matches both the original @orig:: and the new 379 @racket[:], but not other @racketid[:] identifiers. 380 381 It can be used to write macros which expect either 382 @racketid[:] identifier.} 383 384 @subsection{Syntax classes for types} 385 386 @defidform[#:kind "syntax-parse syntax class" 387 type]{ 388 Matches a type. For now, this is just an alias for @racket[expr], because types 389 can contain arbitrary syntax thanks to type expanders.} 390 391 @defthing[stx-type/c flat-contract?]{ 392 Flat contract which recognises syntax objects representing types. For now, 393 this is just an alias for @racket[syntax?], because types can contain 394 arbitrary syntax thanks to type expanders. 395 396 Future versions may implement this as a non-flat contract, in order to be 397 able to check that in a macro's result, the syntax for a type is not used as 398 an expression, and vice versa.} 399 400 @defidform[#:kind "syntax-parse syntax class" 401 type-expand!]{ 402 Matches a type @racket[_t], and provides an attribute named @racket[expanded] 403 which contains the result of @racket[(expand-type #'_t)]. For now, 404 @racket[type-expand] does not perform any check other than verifying that 405 @racket[_t] is an @racket[expr], because types can contain arbitrary syntax 406 thanks to type expanders.} 407 408 @section{multi-id} 409 410 @; TODO: separate multi-id or type-expander into two packages, so that we can 411 @; write @racketmodname[multi-id] without causing a circular dependency: 412 Type expanders are supported by the multi-id library. It is 413 therefore easy to define an identifier which acts as a type 414 expander and match expander as well as a regular racket 415 macro and/or 416 @tech[#:doc '(lib 417 "scribblings/guide/guide.scrbl")]{identifier macro}. This 418 can be useful to define feature-rich data structures, which 419 need to provide all of the above features. 420 421 @section{Expansion model for type expanders} 422 423 The expansion model for type expanders is similar to the expansion model for 424 macros. There are a few differences, however, which are presented below. 425 426 @itemlist[ 427 @item{When a form like @racket[(f args ... . rest)] is encountered, if its 428 first element, @racket[f], is a type expander, the type expander is applied to 429 the whole form. If @racket[f] is a special identifier (e.g. like @racket[Let] 430 or @racket[Rec]), then the form is handled according to the special 431 identifier's rules. Otherwise, the @racket[f] form is expanded, and the result 432 @racket[(e args ... . rest)] is expanded once again (@racket[e] being the 433 result of the expansion of @racket[f]). 434 435 In comparison, the ``official'' macro expander for Racket would, in the last 436 case, expand @racket[f] on its own, and then expand the arguments one by one 437 without re-considering the form as a whole. 438 439 440 With the type expander, during the second expansion pass for the form, if the 441 @racket[e] identifier is a type expander it is applied to the whole form. If 442 @racket[e] is a special identifier, the form is processed following that 443 identifier's rules. Otherwise, the @racket[e] form is left intact, and the 444 arguments @racket[args ...] and @racket[rest] are expanded each in turn. 445 446 In comparison, the ``official'' macro expander would have fully expanded 447 @racket[e] in isolation (e.g. as an identifier macro), without letting it take 448 over the arguments.} 449 @item{With the ``official'' macro expander, all forms at the same lexical 450 scoping level are expanded before expanding the contents of @racket[let] 451 forms. 452 453 In contrast, the type expander expands the contents of @racket[Let] forms in 454 the same order as other forms. It further replaces the @racket[Let] forms by 455 their contents, so that the following type: 456 457 @racketblock[((Let ([Foo Pairof]) Foo) Number String)] 458 459 gets expanded by replacing @racket[(Let ([Foo Pairof]) Foo)] by its contents 460 (i.e. the @racket[Foo] identifier in this case): 461 462 @racketblock[(Foo Number String)] 463 464 The @racket[Foo] identifier is still bound to @racket[Pairof], so this new 465 type expression gets expanded to: 466 467 @racketblock[(Pairof Number String)] 468 469 This means that identifiers bound by @racket[Let] forms can escape their 470 scope, but are still attached to their defining scope.} 471 @item{With the current implementation of the type expander, 472 @racket[syntax-local-value] ignores types bound by @racket[Let] forms. A 473 future version of this library will (hopefully) either fix this problem, or 474 provide an alternative @racket[syntax-local-type-value] which takes those 475 bindings into account.}] 476 477 @section{Built-in type expanders} 478 479 There are several built-in expanders. Some are documented 480 here, while others are listed in 481 @secref["Cases_handled_by_expand-type" 482 #:doc '(lib "type-expander/type-expander.hl.rkt")]. 483 Their API should be considered unstable, and may change in 484 the future. 485 486 @subsection{Let} 487 488 @defform[#:kind "type expander" 489 (Let ([Vᵢ Eᵢ] …) τ) 490 #:grammar 491 ([Vᵢ Identifier] 492 [Eᵢ Type] 493 [τ Type])]{ 494 The @racket[Let] form binds each type expression 495 @racket[Eᵢ] (which may contain uses of type expanders bound 496 outside of the @racket[Let] form) to the identifier @racket[Vᵢ]. 497 The type @racket[τ] can contain type expanders and can 498 refer to occurrences of the bound @racket[Vᵢ] identifiers, 499 which will expand to @racket[Eᵢ]. The @racket[Let] form therefore 500 behaves is a way similar to @racket[let-syntax]. 501 502 @examples[#:eval (eval-factory) 503 (ann '(1 2 3) 504 (Let ([Foo Number]) 505 (Listof Foo))) 506 (eval:error (ann '(1 2 3) 507 (Listof Foo)))] 508 509 @examples[#:eval (eval-factory) 510 (ann '([1 . "a"] [2 . b] [3 . 2.71]) 511 (Let ([Foo (Λ (_ T) 512 #'(Pairof Number T))]) 513 (List (Foo String) 514 (Foo Symbol) 515 (Foo Float))))] 516 517 @examples[#:eval (eval-factory) 518 (ann '(a b c) 519 (Let ([Foo Number]) 520 (Let ([Foo String]) 521 (Let ([Foo Symbol]) 522 (Listof Foo))))) 523 (ann '(a b c) 524 (Let ([Foo Number]) 525 (Listof (Let ([Foo String]) 526 (Let ([Foo Symbol]) 527 Foo)))))]} 528 529 @subsection{Letrec} 530 531 @defform[#:kind "type expander" 532 (Letrec ([Vᵢ Eᵢ] …) τ)]{ 533 Like @racket[Let], but all the @racket[Vᵢ] identifiers are bound within all 534 the @racket[Eᵢ] type expressions. This means the type expression within an 535 @racket[Eᵢ] can refer to any @racket[Vᵢ] of the same @racket[Letrec].} 536 537 538 @subsection{Let*} 539 540 @defform[#:kind "type expander" 541 (Let* ([Vᵢ Eᵢ] …) τ)]{ 542 Like @racket[Let], but all the preceding @racket[Vᵢ] identifiers are bound 543 each @racket[Eᵢ] type expression. This means the type expression within an 544 @racket[Eᵢ] can refer to any @racket[Vᵢ] already bound above it, but not to 545 the @racket[Vᵢ] it is being bound to, nor to the following @racket[Vᵢ].} 546 547 @subsection{Λ} 548 549 @defform[#:kind "type expander" 550 (Λ formals . body) 551 #:grammar 552 ([stx Identifier])]{ 553 554 The @racket[Λ] form (a capital @racketid[λ]) can be used to construct an 555 anonymous type expander. It is equivalent to replacing the whole 556 @racket[(Λ formals . body)] form with @racket[_generated-id], where 557 @racket[_generated-id] is defined as a named type expander as follows: 558 559 @racketblock[(define-type-expander (_gen-id _gen-stx-id) 560 (auto-syntax-case _gen-stx-id () 561 [formals (let () . body)]))] 562 563 where @racket[_id] and @racket[_gen-stx-id] are fresh unique identifiers. 564 565 Since @racket[Λ] relies on @racket[auto-syntax-case], the syntax pattern 566 variables bound by @racket[formals] can also be used outside of syntax 567 templates, in which case they evaluate to @racket[(syntax->datum #'pvar)]. 568 569 @examples[#:eval (eval-factory) 570 #:escape UNSYNTAX 571 (eval:no-prompt (require (for-syntax racket/list racket/function))) 572 (ann '(1 2 3 4) 573 ((Λ (_ T n) 574 #`(List #,@(map (const #'T) (range n)))) 575 Number 4))]} 576 577 @subsection{Quasiquote} 578 579 The type expander library also adds support for 580 quasiquoting in types: The type @racket[`(a (1 b) ,String)] 581 is expanded to @racket[(List 'a (List 1 'b) String)]. 582 583 @examples[#:eval (eval-factory) 584 (ann '(a (1 b) "foo") 585 `(a (1 b) ,String))] 586 587 The @racket[quote], @racket[quasiquote], @racket[syntax] and 588 @racket[quasisyntax] identifiers are interpreted specially within type 589 expressions. The @racket[quote] identifier can be used to describe a type 590 matching containing only the quoted value. Similarly, @racket[syntax] can be 591 used to describe the type of the quoted syntax object, without the need to 592 insert @racket[Syntaxof] by hand around each part of the type. Note that the 593 type @racket[#'(a b c)] will match the syntax object @racket[#'(a b c)], but 594 not the syntax object @tt{#'(a b . (c))}, i.e. the generated type is 595 sensitive to the distinction between syntax pairs and syntax lists. It is 596 possible that a future version of this library provides another type expander 597 which accepts both. The @racket[quasiquote] and @racket[quasisyntax] forms 598 allow the use of @racket[unquote] and @racket[unsyntax], respectively. 599 600 @subsection{Currying type expanders} 601 602 The @racket[curry] special type-expander form can be used to curry in some 603 arguments to a type expander. 604 605 @examples[#:eval (eval-factory) 606 (ann '([a . 1] [a . b] [a . "c"]) 607 (Let ([PA (curry Pairof 'a)]) 608 (List (PA 1) (PA 'b) (PA "c"))))] 609 610 @section{Common issues (FAQ)} 611 612 @(require (only-in scribble/eval interaction)) 613 @itemlist[ 614 @item{Explicitly requiring @racketmodname[typed/racket] 615 causes an error: 616 @(let ([errmsg (string-append "module: identifier already imported from" 617 " a different source in:" "\n" 618 " λ:" "\n" 619 " type-expander" "\n" 620 " typed/racket" "\n")]) 621 @interaction[(eval:alts (require typed/racket type-expander) 622 (eval:result "" 623 "" 624 errmsg))]) 625 A required module can shadow the definitions provided by 626 the @litchar{#lang} language, but it cannot shadow the 627 definitions provided by other explicitly required 628 modules. 629 630 The solution is to avoid explicitly requiring 631 @racketmodname[typed/racket], or to subtract from it the 632 identifiers that would otherwise be shadowed anyway: 633 634 @racketblock[ 635 (require racket/require 636 (subtract-in typed/racket type-expander) 637 type-expander)]} 638 @item{An error complains that a type expander is unbound: 639 @(let ([errmsg (string-append "Type Checker: parse error in type;\n" 640 " type name `foo' is unbound")]) 641 @interaction[(eval:alts (module main typed/racket 642 (module m type-expander/lang 643 (provide foo) 644 (define-type-expander (foo stx) #'Void)) 645 (require 'm) 646 (: v foo) 647 (define v (void))) 648 (eval:result "" 649 "" 650 errmsg))]) 651 652 This error will be raised if the @racketmodname[type-expander] library is not 653 @racket[require]d. It is best to double-check that a 654 @racket[(require type-expander)] form is present, and that it is present at 655 the appropriate meta-level (it should be loaded at the same meta-level as the 656 use of @racket[(: var type)], @racket[(define var : type value)]). 657 658 In the example above, the problem is that the module @racketid[main] requires 659 @racket['m], but does not require @racketmodname[type-expander]. The @orig:: 660 in @racket[(#,orig:: #,(racketid v) #,(racketid foo))] therefore comes from 661 @racketmodname[typed/racket], and does not know how to use the @racketid[foo] 662 type expander.} 663 @item{@bold{Q:} Can I write a recursive type-level 664 function? 665 666 @bold{A:} Yes, but be sure that it is not infinitely 667 recursive, as the expansion would never terminate, unlike 668 @racketmodname[typed/racket]'s @racket[Rec], which allows 669 truly recursive types. 670 671 Furthermore, it is best to ponder the risk of 672 combinatorial explosion, for example in 673 @racketmodname[typed/racket], 674 @racket[((∀ (X) (List X X)) Number)] expands internally to 675 the type @racket[(List Number Number)]. Nesting this 676 pattern a few times will produce a type having an 677 in-memory representation whose size is exponential in the 678 size of the original type declaration. A type expander can 679 easily produce a very large type, which will bring the 680 type checker to a crawl and/or crash it.}] 681 682 @section{Overloaded @racketmodname[typed/racket] primitives} 683 684 685 @defform[(unsafe-cast value type)]{ 686 We define an @racket[unsafe-cast] form which is not (yet) provided by 687 Typed/Racket. It works like @racket[cast], but does not generate a predicate 688 to check that the value is indeed of the given type. It can therefore be used 689 to cast values to types for which @racket[cast] would fail at compile-time 690 when trying to generate the predicate, for example function types, or any type 691 which translates to a 692 @tech[#:doc '(lib "scribblings/reference/reference.scrbl")]{chaperone} 693 contract.} 694 695 @defform[(unsafe-cast/no-expand value type)]{ 696 Like @racket[unsafe-cast], but does not expand the type. Can be useful for 697 types which are not completely handled by @racketmodname[type-expander], for 698 example function types with filters.} 699 700 @(require (for-syntax racket/function racket/struct racket/vector)) 701 @(define-for-syntax (strip-loc e) 702 (cond [(syntax? e) (datum->syntax e (strip-loc (syntax-e e)) #f)] 703 [(pair? e) (cons (strip-loc (car e)) (strip-loc (cdr e)))] 704 [(vector? e) (vector-map strip-loc e)] 705 [(box? e) (box (strip-loc (unbox e)))] 706 [(prefab-struct-key e) 707 => (λ (k) (apply make-prefab-struct 708 k 709 (strip-loc (struct->list e))))] 710 [else e])) 711 712 @(define-syntax (ovl stx) 713 (syntax-case stx () 714 [(_ name ...) 715 (with-syntax ([(prefixed ...) 716 (stx-map (λ (id) (format-id id "orig:~a" id)) 717 #'(name ...))] 718 [(stripped-name ...) 719 (stx-map strip-loc 720 #'(name ...))] 721 [(stripped-ooo ...) 722 (stx-map (compose strip-loc stx-car stx-cdr) 723 #'([name (... ...)] ...))]) 724 #'(list 725 @defform[(stripped-name stripped-ooo)]{ 726 Overloaded version of @|prefixed| from 727 @racketmodname[typed/racket].} 728 ...))])) 729 730 @ovl[ 731 : 732 :type 733 :print-type 734 :query-type/args 735 :query-type/result 736 define-type 737 define 738 lambda 739 λ 740 case-lambda 741 case-lambda: 742 struct 743 define-struct/exec 744 ann 745 cast 746 inst 747 let 748 let* 749 let-values 750 make-predicate 751 ;; 752 class] 753 754 @defidform[...*]{ 755 Overloaded version of @racketid[...*], which is interpreted specially by 756 @racketmodname[typed/racket]. It seems to be equivalent to @racket[*] for 757 indicating the type of a rest argument within a typed @orig:λ form.} 758 759 @section{Unimplemented @racketmodname[typed/racket] 760 primitives (will be overloaded in later versions).} 761 762 @(define-syntax (ovl-todo stx) 763 (syntax-case stx () 764 [(_ name ...) 765 (with-syntax ([(prefixed ...) 766 (stx-map (λ (id) (format-id id "orig:~a" id)) 767 #'(name ...))] 768 [(stripped-name ...) 769 (stx-map strip-loc 770 #'(name ...))] 771 [(stripped-ooo ...) 772 (stx-map (compose strip-loc stx-car stx-cdr) 773 #'([name (... ...)] ...))]) 774 #'(list 775 @defform[(stripped-name stripped-ooo)]{ 776 Overloaded version of @|prefixed| from 777 @racketmodname[typed/racket] (not implemented for the 778 @racketmodname[type-expander] library yet, just throws an 779 error).} 780 ...))])) 781 782 @ovl-todo[ 783 ;; TODO: add all-defined-out in prims.rkt 784 ;; top-interaction.rkt 785 ;; case-lambda.rkt 786 pcase-lambda: 787 ;; (submod "prims-contract.rkt" forms) 788 require/opaque-type 789 ;require-typed-struct-legacy 790 require-typed-struct 791 ;require/typed-legacy 792 require/typed 793 require/typed/provide 794 require-typed-struct/provide 795 ;cast 796 define-predicate 797 ;; prims.rkt 798 define-type-alias 799 define-new-subtype 800 define-typed-struct 801 define-typed-struct/exec 802 define-struct: 803 define-struct 804 struct: 805 λ: 806 lambda: 807 letrec 808 letrec-values 809 let/cc 810 let/ec 811 let: 812 let*: 813 letrec: 814 let-values: 815 letrec-values: 816 let/cc: 817 let/ec: 818 for 819 for/list 820 for/vector 821 for/hash 822 for/hasheq 823 for/hasheqv 824 for/and 825 for/or 826 for/sum 827 for/product 828 for/lists 829 for/first 830 for/last 831 for/fold 832 for* 833 for*/list 834 for*/lists 835 for*/vector 836 for*/hash 837 for*/hasheq 838 for*/hasheqv 839 for*/and 840 for*/or 841 for*/sum 842 for*/product 843 for*/first 844 for*/last 845 for*/fold 846 for/set 847 for*/set 848 do 849 do: 850 with-handlers 851 define-struct/exec:] 852 853 @include-section{deprecated-colon.scrbl} 854 855 @include-section{contracts-to-types.scrbl}