我正在类型化Racket中使用哈希表,并尝试使用来自racket/hash的(非类型化)racket/hash函数。使用require/typed将其导入我的模块并调用它,它将传递类型检查器并进行编译。
#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)))但是,实际运行它将导致合同失败:
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
...普通球拍中的等价物运行良好。如果我正确地读取回溯跟踪,它似乎在测试表是否不可变(虽然我不知道为什么涉及伴侣契约,也不知道它为什么要获得其他值)。将rest类型更改为Immutable-HashTable不会改变任何事情,TR的for/hasheqv返回的表是不可变的。
对是什么原因以及如何解决它有什么想法吗?(除了使用for/fold或其他替代方法构建最终表之外,如果我不能用hash-union解决这个问题,这就是我的计划)。
发布于 2022-07-30 12:07:30
问题是,当您从非类型化的Racket中导入时,哈希表键中的多态不能很好地工作在输入Racket的契约中。错误信息:
hash/c: contract violation
expected: chaperone-contract?
given: k33提到k33,它来自于(All (k v) .... (Immutable-HashTable k v) ....)中的k。
修复此错误的第一步是使用像Any这样的具体类型,而不是多态k,就像在(All (v) .... (Immutable-HashTable Any v) ....)中那样。
之后的下一个错误可能如下所示:
hash-union: contract violation
expected: "hash-equal? (because the key contract is not a flat contract)"
given: '#hasheqv()这是因为hasheq和hasheqv不能很好地处理输入Racket的合同。您可以使用hash或hashalw来修复这个问题,就像在(for/hash : (Immutable-HashTable Any Integer) ....)中一样。
如果您遇到了其他无法以类似方式解决的合同问题,也可以通过不安全地导入它,从而绕过提交给它的合同,但这应该是最后的解决办法。
https://stackoverflow.com/questions/73175239
复制相似问题