typed-racket

How to Reference Existential Type Variables Inside Function Definition?


What's racket analogue of Haskell's ScopedTypeVariables? eg. in

(: f (All (k v l w)
          (-> (Listof k)
              (HashTable k v)
              (-> k v (Values l w))
              (HashTable l w))))
(define (f keys m g)
  (foldl (λ ([k : k] [m : (HashTable k v)]) ;; uh-oh!
           (let-values ([(l w) (g k (hash-ref m k))])
             (hash-set m l w)))
         #hash()
         keys))

k & v are out of scope! How can I get the existential variables bound in the All form in scope in the lambda?


Solution

  • You are misdiagnosing the problem. k, v, l and w are in scope as type variables, but the types are incompatible (k can't unify with l and v can't unify with w). A different function that shows the type variables l and w working in the scope of the function-body, is this example:

    (: f (All (k v l w)
           (-> (Listof k)
               (HashTable k v)
               (-> k v (Values l w))
               (HashTable l w))))
    (define (f keys m g)
      (foldl (λ ([k : k] [acc : (HashTable l w)]) ; can refer to l and w
               (let-values ([(l w) (g k (hash-ref m k))])
                 (hash-set acc l w)))
             (ann #hash() (HashTable l w)) ; can refer to l and w
             keys))