<div dir="ltr">Thank you :) I think the existence of a statically typed language with such heavy support for macros means there's a lot of interesting new directions to experiment in. You could probably build half the syntactic features of Haskell on top of Typed Racket with surprisingly little effort.</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Nov 13, 2014 at 3:31 PM, Sam Tobin-Hochstadt <span dir="ltr"><<a href="mailto:samth@cs.indiana.edu" target="_blank">samth@cs.indiana.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">That's really cool.<br>
<span class="HOEnZb"><font color="#888888"><br>
Sam<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
On Thu, Nov 13, 2014 at 6:28 PM, Jack Firth <<a href="mailto:jackhfirth@gmail.com">jackhfirth@gmail.com</a>> wrote:<br>
> That was my general approach, however I had to do a bit more analysis. That<br>
> macro expands (:/c f (A B) (-> B (-> A B)) to (: f (All (A) (-> B (All (B)<br>
> (-> A B))))). I’ve come up with something that checks the argument types in<br>
> a basic function contract and only provides the polymorphic variables that<br>
> are used, then wraps the returned function type with any unused type<br>
> variables. It's combined with some useful syntax for complex function types.<br>
> The source is available at <a href="https://github.com/jackfirth/compact-annotations" target="_blank">https://github.com/jackfirth/compact-annotations</a><br>
> and it’s available as a package in the catalog. Let’s you write polymorphic<br>
> types much more neatly:<br>
><br>
> (:: map-list-to-vector A B => (Listof A) -> (A -> B) -> (Vectorof B))<br>
> (define ((map-list-to-vector lst) f)<br>
>   (list->vector (map f lst)))<br>
><br>
> If anyone’s interested in this, or if there’s any other shortcuts for type<br>
> annotations people are interested in, I’d love some feedback.<br>
><br>
><br>
> On Wed, Nov 12, 2014 at 7:20 PM, Matthias Felleisen <<a href="mailto:matthias@ccs.neu.edu">matthias@ccs.neu.edu</a>><br>
> wrote:<br>
>><br>
>><br>
>> Sorry that was a superfluous (premature) require:<br>
>><br>
>> #lang typed/racket<br>
>><br>
>> ;; syntax<br>
>> ;; (:/c  f (α β γ) (-> A B (-> C (-> D E))))<br>
>> ;; ==><br>
>> ;; (: f (All (α) (-> A B (All (β) (-> C (All (γ) (-> D E)))))))<br>
>> (define-syntax (:/c stx)<br>
>>   (syntax-case stx (All/c)<br>
>>     [(_ f (A ...) τ) (let ([σ (All/c #'(A ...) #'τ)]) #`(: f #,σ))]))<br>
>><br>
>> ;; [List-of Syntax/id] Syntax -> Syntax<br>
>> ;; distributes type variables along the right-most spine of a curried -><br>
>> type<br>
>> ;; given:<br>
>> ;;  (α β γ) (-> A B (-> C (-> D E)))<br>
>> ;; wanted:<br>
>> ;; (All (α) (-> A B (All (β) (-> C (All (γ) (-> D E))))))<br>
>> (define-for-syntax (All/c α* C)<br>
>>   (syntax-case α* ()<br>
>>     [() C]<br>
>>     [(α) #`(All (α) #,C)]<br>
>>     [(α β ...)<br>
>>      (syntax-case C ()<br>
>>        [(-> A ... B) #`(All (α) (-> A ... #,(All/c #'(β ...) #'B)))]<br>
>>        [(_ (α ...) A) #'(All (α ...) A)])]))<br>
>><br>
>> ;;<br>
>> -----------------------------------------------------------------------------<br>
>><br>
>> (:/c compare-projection (A B) (-> (-> A A Boolean) (-> (-> B A) (-> B B<br>
>> Boolean))))<br>
>> (define (((compare-projection a<) b->a) b1 b2)<br>
>>   (a< (b->a b1) (b->a b2)))<br>
>><br>
>> (define symbol<?<br>
>>   ((compare-projection bytes<?) (compose string->bytes/utf-8<br>
>> symbol->string)))<br>
>><br>
>> (symbol<? 'a 'b)<br>
>><br>
>><br>
>><br>
>> On Nov 12, 2014, at 9:58 PM, Matthias Felleisen wrote:<br>
>><br>
>> ><br>
>> > You cannot write macros that expand within types (yet).<br>
>> ><br>
>> > But you can write macros for : like this:<br>
>> ><br>
>> > #lang typed/racket<br>
>> ><br>
>> > (require (for-template (only-in typed/racket All ->)))<br>
>> ><br>
>> > ;; syntax<br>
>> > ;; (:/c  f (α β γ) (-> A B (-> C (-> D E))))<br>
>> > ;; ==><br>
>> > ;; (: f (All (α) (-> A B (All (β) (-> C (All (γ) (-> D E)))))))<br>
>> > (define-syntax (:/c stx)<br>
>> >  (syntax-case stx (All/c)<br>
>> >    [(_ f (A ...) τ) (let ([σ (All/c #'(A ...) #'τ)]) #`(: f #,σ))]))<br>
>> ><br>
>> > ;; [List-of Syntax/id] Syntax -> Syntax<br>
>> > ;; distributes type variables along the right-most spine of a curried -><br>
>> > type<br>
>> > ;; given:<br>
>> > ;;  (α β γ) (-> A B (-> C (-> D E)))<br>
>> > ;; wanted:<br>
>> > ;; (All (α) (-> A B (All (β) (-> C (All (γ) (-> D E))))))<br>
>> > (define-for-syntax (All/c α* C)<br>
>> >  (syntax-case α* ()<br>
>> >    [() C]<br>
>> >    [(α) #`(All (α) #,C)]<br>
>> >    [(α β ...)<br>
>> >     (syntax-case C ()<br>
>> >       [(-> A ... B)<br>
>> >        (let ([rst (All/c #'(β ...) #'B)])<br>
>> >          #`(All (α) (-> A ... #,rst)))]<br>
>> >       [(_ (α ...) A) #'(All (α ...) A)])]))<br>
>> ><br>
>> > ;;<br>
>> > -----------------------------------------------------------------------------<br>
>> ><br>
>> > (:/c compare-projection (A B) (-> (-> A A Boolean) (-> (-> B A) (-> B B<br>
>> > Boolean))))<br>
>> > (define (((compare-projection a<) b->a) b1 b2)<br>
>> >  (a< (b->a b1) (b->a b2)))<br>
>> ><br>
>> > (define symbol<?<br>
>> >  ((compare-projection bytes<?) (compose string->bytes/utf-8<br>
>> > symbol->string)))<br>
>> ><br>
>> > (symbol<? 'a 'b)<br>
>> ><br>
>> ><br>
>> ><br>
>> > On Nov 12, 2014, at 8:56 PM, Jack Firth wrote:<br>
>> ><br>
>> >> I've been mucking around with Typed Racket some and was writing a<br>
>> >> polymorphic curried function when something I found counter-intuitive popped<br>
>> >> up. I had this function:<br>
>> >><br>
>> >>    (: compare-projection (All (A B) (-> (-> A A Boolean) (-> (-> B A)<br>
>> >> (-> B B Boolean)))))<br>
>> >>    (define (((compare-projection a<) b->a) b1 b2)<br>
>> >>      (a< (b->a b1) (b->a b2)))<br>
>> >><br>
>> >> The purpose of this function was to let me compare things by converting<br>
>> >> them to some other type with a known comparison function, so something like<br>
>> >> symbol<? (which is defined in terms of bytes<? according to the docs) could<br>
>> >> be implemented directly like this:<br>
>> >><br>
>> >>    (define symbol<? ((compare-projection bytes<?) (compose<br>
>> >> string->bytes/utf-8 symbol->string)))<br>
>> >><br>
>> >> The problem I was having was that the first initial argument, bytes<?,<br>
>> >> only specifies the first type variable A. The other type variable B can<br>
>> >> still be anything, as it depends on what function you use to map things to<br>
>> >> type A in the returned function. The All type therefore assumes Any type for<br>
>> >> B, making the returned type non-polymorphic.<br>
>> >><br>
>> >> I expected something like currying to occur in the polymorphic type,<br>
>> >> since the returned type is a function. I thought that if a polymorphic<br>
>> >> function 1) returns a function and 2) doesn't have enough information from<br>
>> >> it's arguments to determine all it's type variables, that it should then<br>
>> >> automatically return a polymorphic function. In other words, I thought this<br>
>> >> type would be equivalent to this automatically:<br>
>> >><br>
>> >>    (All (A) (-> (-> A A Boolean) (All (B) (-> (-> B A) (-> B B<br>
>> >> Boolean)))))<br>
>> >><br>
>> >> This is most certainly not the case, though I wonder - would it be<br>
>> >> terribly difficult to define some sort of polymorphic type constructor that<br>
>> >> *did* behave like this? I'm fiddling with some macros for syntactic sugar of<br>
>> >> type definitions and it would be a boon to not have to worry about this.<br>
>> >> ____________________<br>
>> >> Racket Users list:<br>
>> >> <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
>> ><br>
>> ><br>
>> > ____________________<br>
>> >  Racket Users list:<br>
>> >  <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
>><br>
><br>
><br>
> ____________________<br>
>   Racket Users list:<br>
>   <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
><br>
</div></div></blockquote></div><br></div>