diff --git a/graph-lib/graph/adt.scrbl b/graph-lib/graph/adt.scrbl new file mode 100644 index 0000000..18de762 --- /dev/null +++ b/graph-lib/graph/adt.scrbl @@ -0,0 +1,125 @@ +#lang scribble/manual + +@(require (for-label typed/racket/base + "adt.lp2.rkt") + "../lib/doc.rkt") +@doc-lib-setup + +@defform[#:kind "type expander" + (tagged tag field-desc) + #:grammar + [(tag Identifier) + (field-desc field + [field] + [field : type]) + (field Identifier) + (type Type)]]{ + Expands to the type for a tagged structure with the given + type and fields. If the types for the fields are not given, + a polymorphic structure is returned. + + For now, either all types must be given or none, as + keeping track of which fields are polymorphic and which are + not would be difficult for the user. In the rare cases + whrere partially polymorphic fields would be needed, the + type can easily be described using: + + @racketblock[ + (define-type (partially-polymorphic A C) + (tagged some-tag [a A] [b String] [c C] [d Integer]))]} + +@defform[#:kind "match expander" + (tagged)]{ +} + +@defform*[((tagged maybe-instance tag just-field …) + (tagged maybe-make-instance tag field+value …)) + #:grammar + [(maybe-instance (code:line) + #:instance) + (maybe-make-instance (code:line) + #:make-instance) + (tag Identifier) + (just-field field + [field] + [field : type]) + (field+value [field value] + [field : type value]) + (field Identifier) + (type Type) + (value Expression)]]{ + When using the @racket[just-field] syntax, this form + produces a function which can be used to build an instance + of the tagged structure, by passing as many values as there + are fields. + + When using the @racket[field+value] syntax, this form + directly returns an instance of the tagged structure, with + the given values. + + It is mandatory to disambiguate with either + @racket[#:instance] or @racket[#:make-instance] when using + @racket[tagged] with an empty list of fields (i.e. a + structure with no fields) as it cannot be guessed from the + syntax otherwise, so it is best to always include it when + producing a call to @racket[tagged] in a macro.} + +@defform[(tagged? tag field …) + #:contracts ([tag Identifier] + [field Identifier])]{ + Returns a predicate for tagged structures with the given + @racket[tag] and @racket[field]s.} + +@defform[(tagged? tag + #:with-struct with-struct + field)]{ + The @racket[#:with-struct] option is reserved for internal + use. It is used by @racket[#:private] and + @racket[#:uninterned] in @racket[define-contructor] and + @racket[define-tagged].} + +@defidform[#:kind "type" + TaggedTop]{ + The supertype of all tagged structures.} + +@defproc[(TaggedTop?) Boolean]{ + Predicate for tagged structures. It will also return + @racket[#t] for constructors which only value is a promise + @note{The reason why we wrap the structure with a promise + is to allow building circular data structures, like what + is done in the @racket[graph] library. The structure is + always wrapped in a promise even for non-cyclic data + structures, so that the @racket[get] operation always + operates on the same type. Although this incurs an extra + cost in terms of memory usage, it avoids combinatorial + blowup of the size of the type of an object which has the + nested fields @racket[.f₁.f₂.f₃.….fₙ], which would + otherwise have size @${2ⁿ}, due to the presence of a + @racket[(U (Promise …) …)] at each level.} for a + structure, because this is how tagged structures are + implemented behind the scenes.} + +@defform[(define-constructor name maybe-private-uninterned maybe-? type …) + #:grammar + [(maybe-private-uninterned (code:line) + #:private + #:uninterned) + (maybe-? (code:line) + (code:line #:? name?)) + (name Identifier) + (name? Identifier) + (type Type)]]{ + Binds @racket[name] to the constructor's type-expander, + match-expander and creation function. @racket[name?] is + bound to the predicate for that constructor. + + Unless specified, @racket[name?] is derived from + @racket[name] by appending @racket[?] to the identifier. + + @racket[#:private] and @racket[#:uninterned] allow + specifying a constructor which is not visible from other + files or declarations. @racket[#:uninterned] constructors + are subtypes of the default, interened ones, while + @racket[#:private] are directly subtypes of ConstructorTop, + meaning that they won't be matched by a "public" + constructor with the same name.}