<div dir="ltr">Oh-- I think you&#39;re right that the type parameter can matter (it could go over to R as an Integer list and come back as a Boolean list or something).<div><br>Robby</div></div><div class="gmail_extra"><br>
<br><div class="gmail_quote">On Sun, Jan 6, 2013 at 4:08 PM, Sam Tobin-Hochstadt <span dir="ltr">&lt;<a href="mailto:samth@ccs.neu.edu" target="_blank">samth@ccs.neu.edu</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Sorry, that was very silly of me.  That isn&#39;t what&#39;s happening at all,<br>
because type soundness means we don&#39;t need to enforce the<br>
parametricity at all.<br>
<br>
The actual relevant program is:<br>
<br>
(module m racket<br>
<div class="im">  (struct kons (a d))<br>
  (struct mt ())<br>
  (define MT (mt))<br>
  (define (FST v)<br>
    (when (eq? MT v) (error &#39;empty))<br>
    (kons-a v))<br>
  (define (RST v)<br>
    (when (eq? MT v) (error &#39;empty))<br>
    (kons-d v))<br>
  (define (LST . x)<br>
    (if (empty? x)<br>
        MT<br>
        (kons (first x) (apply LST (rest x)))))<br>
  (define (LST/C elem/c)<br>
    (define C (recursive-contract<br>
               (or/c (λ (v) (eq? v MT))<br>
</div>                     (struct/dc kons [a elem/c] [d C]))))<br>
    C)<br>
  (provide/contract<br>
   [LST (-&gt;* () #:rest any/c (LST/C any/c))]<br>
   [FST (-&gt; (LST/C any/c) any/c)]<br>
   [RST (-&gt; (LST/C any/c) (LST/C any/c))])<br>
  )<br>
<br>
However, thinking about this more, it&#39;s an invariant that `kons`<br>
structures are always correctly constructed, and we can rely on them<br>
to have *some* instantiation that typechecks -- that&#39;s why the `any/c`<br>
is ok.  That suggests to me that contract generation for a struct type<br>
applied to simple type variables can always be just the predicate for<br>
that type, which would make Neil very happy.  I want to think about<br>
this more before I&#39;m sure, though.<br>
<br>
Thanks for being patient while I get this wrong in various ways ...<br>
Sam<br>
<br>
On Sun, Jan 6, 2013 at 4:13 PM, Robby Findler<br>
<div class="HOEnZb"><div class="h5">&lt;<a href="mailto:robby@eecs.northwestern.edu">robby@eecs.northwestern.edu</a>&gt; wrote:<br>
&gt; This has a non-chaperone contract being used in a struct/c, I think?<br>
&gt;<br>
&gt; (FST (LST 1 2 3)) =&gt; struct/dc: expected chaperone contracts, but field a<br>
&gt; has #&lt;barrier-contract&gt;<br>
&gt;<br>
&gt; Robby<br>
&gt;<br>
&gt;<br>
&gt; On Sun, Jan 6, 2013 at 2:40 PM, Sam Tobin-Hochstadt &lt;<a href="mailto:samth@ccs.neu.edu">samth@ccs.neu.edu</a>&gt;<br>
&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; On Sun, Jan 6, 2013 at 3:23 PM, Robby Findler<br>
&gt;&gt; &lt;<a href="mailto:robby@eecs.northwestern.edu">robby@eecs.northwestern.edu</a>&gt; wrote:<br>
&gt;&gt; &gt; On Sun, Jan 6, 2013 at 2:18 PM, Sam Tobin-Hochstadt &lt;<a href="mailto:samth@ccs.neu.edu">samth@ccs.neu.edu</a>&gt;<br>
&gt;&gt; &gt; wrote:<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; &gt; The boundaries have the information; that&#39;s how the contracts got<br>
&gt;&gt; &gt;&gt; &gt; inserted<br>
&gt;&gt; &gt;&gt; &gt; in the first place.<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; No, the contracts are parametric contracts using `parametric-&gt;/c`, and<br>
&gt;&gt; &gt;&gt; thus don&#39;t have any information about the types used at all.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; I don&#39;t see why you can&#39;t tag them when something at a boundary and then<br>
&gt;&gt; &gt; check that something at another boundary instead of doing some deep<br>
&gt;&gt; &gt; check.<br>
&gt;&gt;<br>
&gt;&gt; The problem is that I don&#39;t know what to tag them *with*.<br>
&gt;&gt;<br>
&gt;&gt; Consider the following program:<br>
&gt;&gt;<br>
&gt;&gt; #lang racket<br>
&gt;&gt;<br>
&gt;&gt; (struct kons (a d))<br>
&gt;&gt; (struct mt ())<br>
&gt;&gt; (define MT (mt))<br>
&gt;&gt; (define (FST v)<br>
&gt;&gt;   (when (eq? MT v) (error &#39;empty))<br>
&gt;&gt;   (kons-a v))<br>
&gt;&gt; (define (RST v)<br>
&gt;&gt;   (when (eq? MT v) (error &#39;empty))<br>
&gt;&gt;   (kons-d v))<br>
&gt;&gt; (define (LST . x)<br>
&gt;&gt;   (if (empty? x)<br>
&gt;&gt;       MT<br>
&gt;&gt;       (kons (first x) (apply LST (rest x)))))<br>
&gt;&gt; (define (LST/C elem/c)<br>
&gt;&gt;   (define C (recursive-contract<br>
&gt;&gt;              (or/c (λ (v) (eq? v MT))<br>
&gt;&gt;                    (struct/c kons elem/c C))))<br>
&gt;&gt;   C)<br>
&gt;&gt; (provide/contract<br>
&gt;&gt;  [LST (parametric-&gt;/c (A) (-&gt;* () #:rest A (LST/C A)))]<br>
&gt;&gt;  [FST (parametric-&gt;/c (A) (-&gt; (LST/C A) A))]<br>
&gt;&gt;  [RST (parametric-&gt;/c (A) (-&gt; (LST/C A) (LST/C A)))])<br>
&gt;&gt;<br>
&gt;&gt; This is the essence of Neil&#39;s polymorphic list program, as implemented<br>
&gt;&gt; by Typed Racket. I don&#39;t know how to change those contracts to not be<br>
&gt;&gt; really expensive, because I can&#39;t pick the instantiation of A at<br>
&gt;&gt; runtime to tag the structure instances with.<br>
&gt;&gt;<br>
&gt;&gt; Sam<br>
&gt;<br>
&gt;<br>
</div></div></blockquote></div><br></div>