[plt-scheme] Typed Scheme polymorphic variadic functions

From: Anthony Cowley (acowley at seas.upenn.edu)
Date: Tue Mar 17 15:05:42 EDT 2009

On Tue, Mar 17, 2009 at 2:53 PM, David Van Horn <dvanhorn at ccs.neu.edu> wrote:
> Anthony Cowley wrote:
>> I am now having problems with the union type constructor:
>> (U A ... A)
>> is this also not currently supported?
> (U A) = A
> (U A A) = A
> (U A ... A) = A

I think you are mistaken on that last example.

>> This type almost works, but not quite if I (apply check-all
>> list-of-tests):
>> (: check-all (All (A ...) ((List (-> A) A String) ... A -> Void)))
>> Yet, if I write out (check-all (car lot) (cadr lot)) then it's fine
>> (lot = list-of-tests). This might make some sense if type checking is
>> purely syntactic, but since we do know the type of list-of-tests, I
>> was hoping that the apply function could sort things out. Instead, I
>> get an error message such as the following:
>> typecheck: Bad arguments to polymorphic function in apply:
>> Domain: (List (-> A) A String) ... A
>> Arguments: (List (List (-> (Listof Integer)) (Listof Integer) String)
>> (List (-> (Listof Integer)) (Listof Integer) String)) *
> Does your function work in an untyped setting?  I'm guessing no.  Try it out
> first without types.  If it works, then send the code (or some small
> representative of the code).
> David

As I mentioned in my email, if called (check-all test1 test2) then it
works in typed scheme, but when called (apply check-all tests) it does
not. Just for the sake of completeness, here is an example that lets
one flip between typed and untyped to see the problem.

;; Change the lang to scheme for untyped version
#lang typed-scheme

(define tests (list (list (λ() 1) 1 "test 1")
                    (list (λ() 2) 2 "test 2")))

; Comment out the type signature when running untyped
(: check-all (All (A ...) ((List (-> A) A String) ... A -> Void)))
(define (check-all . tests)
  (let aux ([tests tests]
            [num-passed 0])
    (if (null? tests)
        (printf "~a tests passed.~n" num-passed)
        (let ((test (car tests)))
          (let ((actual ((car test)))
                (expected (cadr test))
                (msg (caddr test)))
            (if (equal? actual expected)
                (aux (cdr tests) (+ num-passed 1))
                (printf "Test failed: ~a. Expected ~a, got ~a.~n"
                        msg expected actual)))))))

;(apply check-all tests) ; Works in untyped, but not in typed
(check-all (car tests) (cadr tests)) ; Works in typed or untyped

Posted on the users mailing list.