96 lines
4.0 KiB
Racket
96 lines
4.0 KiB
Racket
#lang scribble/manual
|
|
|
|
@(require scribble-enhanced/manual-form)
|
|
|
|
@(require (for-label typed/racket/base
|
|
"rewrite-type.lp2.rkt"))
|
|
|
|
@title{Rewrite-type utilities for writing type-level functions}
|
|
|
|
The utilities described here allow replacing parts of a
|
|
type with other types, and generating conversion functions
|
|
transforming instances of the old type into instances of the
|
|
new type.
|
|
|
|
@defform[#:kind "procedure"
|
|
(replace-in-type old-type
|
|
#'([from to] …))
|
|
#:result (syntax-for type)
|
|
#:contracts ([old-type (syntax-for type)]
|
|
[from (and/c identifier? (syntax-for type))]
|
|
[to (syntax-for type)])]{
|
|
This type-level function produces the syntax for the
|
|
@racket[new-type]. The @racket[new-type] has the same shape
|
|
as the @racket[old-type], except all occurrences of the
|
|
@racket[from] type (which must be just a single identifier)
|
|
replaced with the @racket[to] type in the type.
|
|
|
|
The @racket[replace-in-type] type-level function first
|
|
expands any @racketmodname[type-expander]s, and performs
|
|
the replacements on the expanded type.}
|
|
|
|
@deftogether[
|
|
(@defform[#:kind "procedure"
|
|
(replace-in-instance old-type
|
|
#'([from to pred? fun] …))
|
|
#:result (syntax-for (→ old-type new-type))]
|
|
@defform[#:kind "template metafunction"
|
|
(tmpl-replace-in-instance old-type
|
|
[from to pred? fun] …)
|
|
#:result (syntax-for (→ old-type new-type))
|
|
#:contracts ([old-type (syntax-for type)]
|
|
[from (and/c identifier? (syntax-for type))]
|
|
[to (syntax-for type)]
|
|
[pred? (syntax-for predicate?)]
|
|
[fun (syntax-for (→ from to))])])]{
|
|
Produces the syntax for the syntax for a function from the
|
|
@racket[old-type] to the @racket[new-type], transforming
|
|
all parts of the data structure which satisfy
|
|
@racket[pred?] using @racket[fun]. The @racket[new-type]
|
|
will be the same as the one that would be returned by
|
|
@racket[(replace-in-type old-type #'([from to] …))]
|
|
|
|
@racket[pred?] should return true if and only if the data
|
|
passed as an argument is an instance of the @racket[from]
|
|
type. @racket[fun] should accept instances of the
|
|
@racket[from] type, and return instances of the
|
|
@racket[to] type.
|
|
}
|
|
|
|
@deftogether[
|
|
(@defform[#:kind "procedure"
|
|
(fold-instance old-type
|
|
accumulator-type
|
|
([from to pred? fun] …))
|
|
#:result (syntax-for
|
|
(→ old-type (Values new-type accumulator-type)))]
|
|
@defform[#:kind "template metafunction"
|
|
(tmpl-fold-instance old-type accumulator-type
|
|
[from to pred? fun] …)
|
|
#:result (syntax-for
|
|
(→ old-type (Values new-type accumulator-type)))
|
|
#:contracts ([old-type (syntax-for type)]
|
|
[accumulator-type (syntax-for type)]
|
|
[from (and/c identifier? (syntax-for type))]
|
|
[to (syntax-for type)]
|
|
[pred? (syntax-for predicate?)]
|
|
[fun (syntax-for (→ from acc (Values to acc)))])])]{
|
|
Produces the syntax for the syntax for a function from the
|
|
@racket[old-type] to the @racket[new-type], transforming
|
|
all parts of the data structure which satisfy
|
|
@racket[pred?] using @racket[fun]. The @racket[new-type]
|
|
will be the same as the one that would be returned by
|
|
@racket[(replace-in-type old-type #'([from to] …))]
|
|
|
|
The generated function takes as a second argument an
|
|
initial value for the accumulator. The accumulator is
|
|
passed to @racket[fun] and the one returned is used as the
|
|
accumulator for the next call. No guarantee is made on the
|
|
order of traversal.
|
|
|
|
@racket[pred?] should return true if and only if the data
|
|
passed as an argument is an instance of the @racket[from]
|
|
type. @racket[fun] should accept instances of the
|
|
@racket[from] type, and return instances of the
|
|
@racket[to] type.}
|