You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 15:48:29