[plt-scheme] Dynamic Contracts

From: Robby Findler (robby at cs.uchicago.edu)
Date: Fri Jul 21 13:59:04 EDT 2006

You can write a contract that ensures that the list has the right
length and has the right elements by using ->d. For more complex things
along these lines, you'll ->pp (or ->r). But, here's your example using
->d

(module m mzscheme
  (require (lib "contract.ss")
           (lib "etc.ss"))
  
  (provide/contract 
   [make-list (->d natural-number/c any/c 
                   (λ (size ele)
                     (and/c (listof (λ (x) (eq? x ele)))
                            (λ (l) (= (length l) size)))))])
  
  (define (make-list x ele)
    ;; this has a bug: call it to get a contract violation.
    (build-list (+ 1 x) (λ (i) ele))))

->d is like ->, except that the last argument is a function that
accepts the inputs to the contracted function and returns a contract.
In this case, it returns a contract specifying the length and the
elements of the list.

As far as the type part of your question goes, the answer is another
question: given this SCheme value '(1 2), what is its type? list of
number? s-expression? list of length 2? All of these are valid types
for that value and, without context, there's no way to know which one
you meant. Note that Scheme is very different from ML in this regard:
in ML, each constructor corresponds to a unique type. Not so in Scheme.

Of course, the above does more than say "same type" -- it says "same
value" which is what you really want to say anyways, no?

Robby

At Fri, 21 Jul 2006 11:27:16 -0500, Chris Warrington wrote:
> Does contract.ss support what I want to call "dynamic contracts?"
> 
> Consider this function:
> ; make-list : natural-number X -> [X]
> ; Creates a list of the given length in which each element
> ; is the provided element.
> (define (make-list count val) ...)
> 
> Using provide/contract (yes, I'm doing this in a module), I can attach a simple
> contract to this:
> (provide/contract [make-list (natural-number/c any/c . -> . (listof any/c))])
> 
> However, this contract can be made stronger. For example, the length of the list
> should be equal to count. However, I can't find a good way to do this.
> Thus far, the best I have is this:
> 
> ; dc:make-list
> ; Dynamic contract for make-list
> (define (dc:make-list count val)
>   ((contract (natural-number/c any/c . -> . (and/c (listof any/c)
>                                                    (λ (lst) (= (length lst)
> count))))
>              make-list
>              'callee
>              'caller)
>    count val))
> 
> Is there an easier way to do these "dynamic contracts?" How would one go about
> enforcing the type contraint in this case (i.e., the list should be of the same
> type as val)?
> 
> --
> Chris Warrington <chrisw at rice.edu>
> (away from his normal computer)
> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme


Posted on the users mailing list.