Typed Racket中使用hash-union触发合约失败的问题排查
Typed Racket使用hash-union触发合约失败的原因与解决办法
问题原因
核心问题出在require/typed对hash-union的类型声明错误:
- Typed Racket的
->*语法中,#:rest参数对应的类型必须是列表类型(表示可变数量的位置参数组成的列表),但你写成了(HashTable k v),而非(Listof (HashTable k v))。 - 错误的类型声明导致Typed Racket生成的合约逻辑混乱,把类型变量的运行时标识(比如报错里的
k33)当成合法合约传递给哈希表检查函数,最终触发chaperone-contract?的合约违反错误。
解决办法
修正require/typed中的hash-union类型声明,将#:rest的类型改为(Listof (HashTable k v)),修正后的完整代码如下:
#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 (Listof (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)))
备选方案(仅当上述方法无效时使用)
如果修正类型声明后仍有合约问题,可以用-unsafe-require/typed替代require/typed,绕过Typed Racket的合约检查(注意:此方法会丢失类型安全保障,仅作为临时 workaround):
#lang typed/racket/base (-unsafe-require/typed racket/hash [hash-union (All (k v) (->* ((Immutable-HashTable k v)) (#:combine (-> v v v) #:combine/key (-> k v v v)) #:rest (Listof (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)))
内容的提问来源于stack exchange,提问作者Shawn
相关产品推荐
相关产品推荐

