On this page:
poly/ c
parametric/ c
memory/ c
opaque/ c
Version: 5.0

14 Polymorphic Contracts

Sam Tobin-Hochstadt <samth@ccs.neu.edu>
and Carl Eastlund <cce@ccs.neu.edu>

 (require unstable/poly-c)

This library is unstable; compatibility will not be maintained. See Unstable for more information.

(poly/c (x ...) c)
Creates a contract for polymorphic functions that may inspect their arguments. Each function is protected by c, where each x is bound in c and refers to a polymorphic type that is instantiated each time the function is applied.

At each application of a function, the poly/c contract constructs a new weak, eq?-based hash table for each x. Values flowing into the polymorphic function (i.e. values protected by some x in negative position with respect to poly/c) are stored in the hash table. Values flowing out of the polymorphic function (i.e. protected by some x in positive position with respect to poly/c) are checked for their presence in the hash table. If they are present, they are returned; otherwise, a contract violation is signalled.

Examples:

  > (define/contract (check x y) (poly/c [X] (boolean? X . -> . X))
      (if (or (not x) (equal? y 'surprise))
          'invalid
          y))
  > (check #t 'ok)

  'ok

  > (check #f 'ignored)

  eval:2.0: (function check) broke the contract (poly/c (X)

  ...) on check; expected a(n) X; got: 'invalid

  > (check #t 'surprise)

  eval:2.0: (function check) broke the contract (poly/c (X)

  ...) on check; expected a(n) X; got: 'invalid

(parametric/c (x ...) c)
Creates a contract for parametric polymorphic functions. Each function is protected by c, where each x is bound in c and refers to a polymorphic type that is instantiated each time the function is applied.

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 signalled.

Examples:

  > (define/contract (check x y) (parametric/c [X] (boolean? X . -> . X))
      (if (or (not x) (equal? y 'surprise))
          'invalid
          y))
  > (check #t 'ok)

  'ok

  > (check #f 'ignored)

  eval:2.0: (function check) broke the contract (parametric/c

  (X) ...) on check; expected a(n) X; got: 'invalid

  > (check #t 'surprise)

  'surprise

(memory/c positive? name)  contract?
  positive? : boolean?
  name : any/c
This function constructs a contract that records values flowing in one direction in a fresh, weak hash table, and looks up values flowing in the other direction, signalling a contract violation if those values are not in the table.

If positive? is true, values in positive position get stored and values in negative position are checked. Otherwise, the reverse happens.

(opaque/c positive? name)  contract?
  positive? : boolean?
  name : any/c
This function constructs a contract that wraps values flowing in one direction in a unique, opaque wrapper, and unwraps values flowing in the other direction, signalling a contract violation if those values are not wrapped.

If positive? is true, values in positive position get wrapped and values in negative position get unwrapped. Otherwise, the reverse happens.