I'm working with hash tables in Typed Racket, and trying to use the (untyped) hash-union function from racket/hash. Using require/typed to import it into my module and call it will pass the type checker and compile.
#lang typed/racket/base
(require/typed racket/hash
[hash-union (All (k v) (->* ((Immutable-HashTable k v))
(#:combine (-> v v v) #:combine/key (-> k v v v))
#:rest (HashTable k v)
(Immutable-HashTable k v)))])
(: pick-first (All (a) (-> a a a)))
(define (pick-first v1 v2) v1)
(: make-ci-table (-> String (Immutable-HashTable Char Integer)))
(define (make-ci-table pat)
(let ([patlen (string-length pat)])
((inst hash-union Char Integer)
(for/hasheqv : (Immutable-HashTable Char Integer) ([i (in-range patlen)])
(values (char-upcase (string-ref pat i)) (- patlen 1 i)))
(for/hasheqv : (Immutable-HashTable Char Integer) ([i (in-range patlen)])
(values (char-downcase (string-ref pat i)) (- patlen 1 i)))
#:combine pick-first)))
However, actually running it will cause a contract failure:
raco test: (submod "main.rkt" test)
hash/c: contract violation
expected: chaperone-contract?
given: k33
context...:
/usr/share/racket/collects/racket/contract/private/hash.rkt:61:0: hash/c
/usr/share/racket/pkgs/typed-racket-lib/typed-racket/utils/hash-contract.rkt:28:0: hash/c/check-key
/usr/share/racket/pkgs/typed-racket-lib/typed-racket/utils/hash-contract.rkt:22:0: immutable-hash/c
/usr/share/racket/collects/racket/contract/private/parametric.rkt:26:36
/usr/share/racket/collects/racket/contract/private/parametric.rkt:82:7: wrap
/usr/share/racket/collects/racket/contract/private/parametric.rkt:100:10
...
The equivalent in normal Racket runs fine. It appears to be failing in testing if a table is immutable if I'm reading that back trace correctly (Though I have no idea why a chaperone contract is involved, or why it's getting some other value). Changing the rest type to Immutable-HashTable doesn't change anything, and the tables returned by TR's for/hasheqv are immutable ones.
Any ideas on what's causing this and how to fix it? (Other than building the final table up with for/fold or some other alternative approach, which is my plan if I can't resolve this issue with hash-union).