In a sense, you put your finger on a sore spot of TR from R -- we are still 
figuring out how to help programmers along here. I rewrote your program like 
this: 

#lang typed/racket

(: 1+ (Nonnegative-Integer -> Positive-Integer))
(define (1+ n)
  (+ n 1))

;; entirely unnecessary but helped me read; IGNORE 
(define-type (Maybe α) (U False α))
(define-type NI Nonnegative-Integer)
(define-type LNI (Listof NI))
(define-type VNI (Vectorof NI))

(let* ((idx+level (map #{vector->list @ NI} (cast '(#(1 2) #(3 4) #(5 6)) 
(Listof VNI))))
       (res (#{make-vector @ [Maybe NI]} (1+ (apply max (map #{car @ NI LNI} 
idx+level))) #f)))
  (for-each (λ ((p : LNI))
              (let ((i (car p))
                    (l (cadr p)))
                (vector-set! res i l)))
            idx+level)
  res)

;; expect 
'#(#f 2 #f 4 #f 6)


I focused on what the type checker really needs -- hints on how to specialize 
those functions, and only those, that depend on your initial insight that the 
TC needs a hand with make-vector. Then I checked on the maps and realized that 
I need to help the TC along with the instantiations of vector->list (how can it 
know with context-free reasoning what kind of vector it is) and the same for 
car (how can it know what kind of list you're getting here). 

[[ Also, I don't know why this code looks like it does. There are alternative: 

#lang typed/racket

(: 1+ (Nonnegative-Integer -> Positive-Integer))
(define (1+ n)
  (+ n 1))

;; entirely unnecessary but helped me read 
(define-type (Maybe α) (U False α))
(define-type NI Nonnegative-Integer)
(define-type LNI (Listof NI))
(define-type VNI (Vectorof NI))

(let* ((i0 (cast '(#(1 2) #(3 4) #(5 6)) [Listof VNI]))
       (idx+level (map #{vector->list @ NI} i0))
       (res (#{make-vector @ [Maybe NI]} (1+ (apply max (map #{car @ NI LNI} 
idx+level))) #f)))
  (for ((q : [Vectorof NI] (in-list i0)))
    (define i (vector-ref q 0))
    (define l (vector-ref q 1))
    (vector-set! res i l))
  res)


]]




On Aug 3, 2014, at 6:46 PM, Norman Gray wrote:

> 
> Greetings.
> 
> Short version: I repeatedly find myself adding TR type annotations by 
> trial-and-error -- I'm sure I'm missing something.
> 
> I had a particularly acute case of this this afternoon.  I have a bit of 
> typed/racket/base code as follows:
> 
> (: 1+ (Nonnegative-Integer -> Positive-Integer))
> (define (1+ n)
>  (+ n 1))
> 
> (define map1 #{map @ (Listof Nonnegative-Integer) (Vectorof 
> Nonnegative-Integer)})
> (define map2 #{map @ Nonnegative-Integer (Listof Nonnegative-Integer)})
> (let* ((idx+level (map1 vector->list
>                        (cast '(#(1 2) #(3 4) #(5 6))
>                              (Listof (Vectorof Nonnegative-Integer)))))
>       (res (#{make-vector @ (U Nonnegative-Integer False)} (1+ (apply max 
> (map2 car idx+level))) #f)))
>  (for-each (λ: ((p : (Listof Nonnegative-Integer)))
>              (let ((i (car p))
>                    (l (cadr p)))
>                (vector-set! res i l)))
>            idx+level)
>  res)
> 
> It doesn't much matter here what this does; but it typechecks and works OK.
> 
> What I'm puzzled by is the amount of explicit type information I had to add, 
> in order to get it to typecheck, and I confess that I added that type 
> annotation by simply going round and round the compile cycle in DrRacket, 
> adding more and more until Racket stopped complaining.   Apart from anything 
> else, the annotations end up making the code less readable than it might 
> otherwise be.
> 
> I can pretty much see why I have to instantiate the make-vector explicitly 
> (it'd probably be asking a bit much for Racket to look around and spot that 
> the only thing called in the third argument of vector-set! is a 
> Nonnegative-Integer), and I can sort-of see why I have to cast the '(#(1 2) 
> ...) list [Racket identifies '(#(1 2) #(3 4) #(5 6)) as  (Listof (Vector 
> Integer Integer)) which is more restricted than (Listof (Vectorof Real)), but 
> less restricted than the actual (Listof (Vectorof Positive-Integer)) ].
> 
> But I can't really see why I have to spell out the instantiations of map1 and 
> map2 (given the types of their arguments, I can unambiguously (?) deduce the 
> type of the instantiation in both cases), and the type of the for-each 
> argument, but I _don't_ have to spell out the type of idx+level.  And I have 
> to spell out the maps , but not the car in (map2 car idx+level).
> 
> I can sort of see that type information propagates 'outwards', so that, for 
> example, the type of map1 (specifically its domain) implies the type of 
> idx+level, which the result of map1 is assigned to.  Analogously, because the 
> type of p is known, then the corresponding car can be instantiated 
> unambiguously.
> 
> However I don't have to instantiate vector->list, or the car argument to 
> map2, so this appears to be type information propagating either 'inwards' 
> from the type of map1/map2, or 'across' from the other argument.
> 
> Working through that, and looking at the simple case of 
> 
>    (map car (cast '((1 2) (3 4) (5 6)) (Listof (Listof Byte)))) ,
> 
> we have map's type as
> 
>    : (All (c a b ...)
>      (case->
>       (-> (-> a c) (Pairof a (Listof a)) (Pairof c (Listof c)))
>       (-> (-> a b ... b c) (Listof a) (Listof b) ... b (Listof c))))
> 
> Now, the type (Listof (Listof Byte)) fixes a in the first clause to be 
> (Listof Byte), and thus, in the type of car
> 
>     : (All (a b) (case-> (-> (Pairof a b) a) (-> (Listof a) a))) ,
> 
> (Pairof a b) is (Listof Byte), meaning that a, here, must be Byte and thus 
> the domain of car must be Byte, fixing c in the type of map.  So there 
> appears to be no ambiguity, and while the algorithm for the general case 
> would clearly be entertainingly challenging (am I correct that this was Sam's 
> PhD work?), I'm not seeing a fundamental blocker.
> 
> In summary, I'm not saying anything's amiss here, but there are rather more 
> 'sort-of's in the above account than I'm comfortable with.
> 
> So: (a) Am I doing something wrong, or writing unidiomatically?; and (b) is 
> there a heuristic to guide me in what annotation I actually need to add and 
> what can be inferred, so it's all a bit less trial-and-error?
> 
> All the best,
> 
> Norman
> 
> 
> -- 
> Norman Gray  :  http://nxg.me.uk
> SUPA School of Physics and Astronomy, University of Glasgow, UK
> 
> 
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users


____________________
  Racket Users list:
  http://lists.racket-lang.org/users

Reply via email to