7.3 Parametric Contracts
(require racket/contract/parametric) |
The most convenient way to use parametric contract is to use contract-out’s #:exists keyword. The racket/contract/parametric provides a few more, general-purpose parametric contracts.
(parametric->/c (x ...) c)
At each application of a function, the parametric->/c contract constructs a new opaque wrapper for each x; values flowing into the polymorphic function (i.e. values protected by some x in negative position with respect to parametric->/c) are wrapped in the corresponding opaque wrapper. Values flowing out of the polymorphic function (i.e. values protected by some x in positive position with respect to parametric->/c) are checked for the appropriate wrapper. If they have it, they are unwrapped; if they do not, a contract violation is signaled.
Examples: | ||||||||||||||||
|
Universal contracts accept all values when in negative positions (e.g., function inputs) and wrap them in an opaque struct, hiding the precise value. In positive positions (e.g. function returns), a universal contract accepts only values that were previously accepted in negative positions (by checking for the wrappers).
The name is used to identify the contract in error messages.
The new-∀/c construct constructor is dual to new-∃/c.
Existential contracts accept all values when in positive positions (e.g., function returns) and wrap them in an opaque struct, hiding the precise value. In negative positions (e.g. function inputs), they accepts only values that were previously accepted in positive positions (by checking for the wrappers).
The name is used to identify the contract in error messages.